ADO.NET2.0 异步处理的三种方式-wait方法

Wait方法是三种异步调用方法中最为优雅的一种,这种方法提供了高度的灵活性,高效性,当然也稍微复杂一点。使用这种方法可以开始多个异步过程然后等待其中任何或者过程调用结束。使用这种方法你可以只等待那些相互依赖的过程,处理那些不和其他过程依赖的异步过程。这种方法在设计上要求考虑异步过程的细节,你必须慎重判断哪些异步过程是相互依赖的,哪些不是。这种方法的复杂性在于你必须理解其细节并且做出对应的设计。这是一种最好的使用异步调用和异步处理模型的代码设计。注意使用WaitHandle类的WaitOne方法来等待异步过程的执行结束。

 

<%@ Page Language=C# %>

<%@ Import Namespace=System.Data %>

<%@ Import Namespace=System.Data.SqlClient %>

<%@ Import Namespace=System.Configuration %>

<script runat=server>

protected void Page_Load(object sender, EventArgs e)

{

SqlConnection DBCon;

SqlCommand Command = new SqlCommand();

SqlDataReader OrdersReader;

IAsyncResult ASyncResult;

System.Threading.WaitHandle WHandle;

DBCon = new SqlConnection();

DBCon.ConnectionString =

ConfigurationManager.ConnectionStrings[DSN_NorthWind].ConnectionString;

Command.CommandText =

SELECT TOP 5 Customers.CompanyName, Customers.ContactName, +

Orders.OrderID, Orders.OrderDate, +

Orders.RequiredDate, Orders.ShippedDate +

FROM Orders, Customers +

WHERE Orders.CustomerID = Customers.CustomerID +

ORDER BY Customers.CompanyName, Customers.ContactName ;

Command.CommandType = CommandType.Text;

Command.Connection = DBCon;

DBCon.Open();

// Starting the asynchronous processing

ASyncResult = Command.BeginExecuteReader();

WHandle = ASyncResult.AsyncWaitHandle;

if (WHandle.WaitOne() == true)

{

// Retrieving result from the asynchronous process

OrdersReader = Command.EndExecuteReader(ASyncResult);

// Displaying result on the screen

gvOrders.DataSource = OrdersReader;

gvOrders.DataBind();

// Closing connection

DBCon.Close();

}

else

{

// Asynchronous process has timed out. Handle this

// situation here.

}

}

</script>

如果你设置断点跟踪代码会发现程序在停在调用WHandle.WaitOne方法的那行代码上。当异步调用结束后程序会继续执行。

  

使用多个Wait句柄

Wait方法在开始多个异步过程的时候其真正威力才能显示出来。其中一个过程查询数据库一个具体的customer的相关信息,另一个查询则处理这个customer提交的所有Order(订单)。下面的代码使用了两个Command对象,data reader对象和wait句柄。这里使用一个connection对象,由此可以看出多活动结果集(MARS)对异步处理的良好支持。

<%@ Page Language=C# %>

 

<%@ Import Namespace=System.Data %>

<%@ Import Namespace=System.Data.SqlClient %>

<%@ Import Namespace=System.Configuration %>

<script runat=server>

protected void Page_Load(object sender, EventArgs e)

{

SqlConnection DBCon;

SqlCommand OrdersCommand = new SqlCommand();

SqlCommand CustCommand = new SqlCommand();

SqlDataReader OrdersReader;

SqlDataReader CustReader;

IAsyncResult OrdersASyncResult;

IAsyncResult CustAsyncResult;

System.Threading.WaitHandle[] WHandles = new

System.Threading.WaitHandle[1];

System.Threading.WaitHandle OrdersWHandle;

System.Threading.WaitHandle CustWHandle;

DBCon = new SqlConnection();

DBCon.ConnectionString =

ConfigurationManager.ConnectionStrings[DSN_NorthWind].ConnectionString;

CustCommand.CommandText =

SELECT * FROM Customers WHERE CompanyName = Alfreds Futterkiste’ “;

CustCommand.CommandType = CommandType.Text;

CustCommand.Connection = DBCon;

// Selecting all orders for a specific customer

SELECT Customers.CompanyName, Customers.ContactName, +

 

Orders.OrderID, Orders.OrderDate, +

Orders.RequiredDate, Orders.ShippedDate +

FROM Orders, Customers +

WHERE Orders.CustomerID = Customers.CustomerID +

AND Customers.CompanyName = Alfreds Futterkiste’ “ +

ORDER BY Customers.CompanyName, Customers.ContactName ;

OrdersCommand.CommandType = CommandType.Text;

OrdersCommand.Connection = DBCon;

DBCon.Open();

// Retrieving customer information asynchronously

CustAsyncResult = CustCommand.BeginExecuteReader();

// Retrieving orders list asynchronously

OrdersASyncResult = OrdersCommand.BeginExecuteReader();

CustWHandle = CustAsyncResult.AsyncWaitHandle;

OrdersWHandle = OrdersASyncResult.AsyncWaitHandle;

// Filling Wait Handles array with the two wait handles we

// are going to use in this code

WHandles[0] = CustWHandle;

WHandles[1] = OrdersWHandle;

System.Threading.WaitHandle.WaitAll(WHandles);

CustReader = CustCommand.EndExecuteReader(CustAsyncResult);

OrdersReader = OrdersCommand.EndExecuteReader(OrdersASyncResult);

gvCustomers.DataSource = CustReader;

gvCustomers.DataBind();

gvOrders.DataSource = OrdersReader;

gvOrders.DataBind();

DBCon.Close();

}

</script>

上面的代码显示了wait方法的优雅,然而在ADO.NET2.0中这不是最有效的代码。代码允许你可以在把结果集绑到到各自的GridView控件之前等待两个异步过程的调用结束。你可以修改代码如下所示以获取更好的效率。用WaitAny方法来代替WaitAllWaitAny方法可以尽快处理一个调用结束的异步过程而不用等待其他过程结束。使用WaitAny方法你依然可以添加循环来保证其他过程调用结束后得到处理。WaitAny方法返回一个整数表示在WaitHanle数组中调用结束的那个异步过程的索引。使用这个返回值你可以得到wait句柄来处理一个已经结束的异步过程所返回的结果。

 

<%@ Page Language=C# %>

<%@ Import Namespace=System.Data %>

<%@ Import Namespace=System.Data.SqlClient%>

<%@ Import Namespace=System.Configuration %>

<script runat=server>

protected void Page_Load(object sender, EventArgs e)

{

SqlConnection DBCon;

SqlCommand OrdersCommand = new SqlCommand();

SqlCommand CustCommand = new SqlCommand();

SqlDataReader OrdersReader;

SqlDataReader CustReader;

IAsyncResult OrdersASyncResult;

IAsyncResult CustAsyncResult;

int WHIndex;

System.Threading.WaitHandle[] WHandles =

new System.Threading.WaitHandle[1];

System.Threading.WaitHandle OrdersWHandle;

System.Threading.WaitHandle CustWHandle;

DBCon = new SqlConnection();

DBCon.ConnectionString =

ConfigurationManager.ConnectionStrings[DSN_NorthWind].ConnectionString;

CustCommand.CommandText =

SELECT * FROM Customers WHERE CompanyName = Alfreds Futterkiste’ “;

CustCommand.CommandType = CommandType.Text;

CustCommand.Connection = DBCon;

OrdersCommand.CommandText =

SELECT Customers.CompanyName, Customers.ContactName, +

Orders.OrderID, Orders.OrderDate, +

Orders.RequiredDate, Orders.ShippedDate +

FROM Orders, Customers +

WHERE Orders.CustomerID = Customers.CustomerID +

AND Customers.CompanyName = Alfreds Futterkiste’ “ +

ORDER BY Customers.CompanyName, Customers.ContactName ;

OrdersCommand.CommandType = CommandType.Text;

OrdersCommand.Connection = DBCon;

// Opening the database connection

DBCon.Open();

 

// Retrieving customer information asynchronously

CustAsyncResult = CustCommand.BeginExecuteReader();

// Retrieving orders list asynchronously

OrdersASyncResult = OrdersCommand.BeginExecuteReader();

CustWHandle = CustAsyncResult.AsyncWaitHandle;

OrdersWHandle = OrdersASyncResult.AsyncWaitHandle;

// Filling Wait Handles array with the two wait handles we

// are going to use in this code

WHandles[0] = CustWHandle;

WHandles[1] = OrdersWHandle;

// Looping 2 times because there are 2 wait handles

// in the array

for (int Index = 0; Index < 2; Index++ )

{

// We are only waiting for any of the two

// asynchronous process to finish running

WHIndex = System.Threading.WaitHandle.WaitAny(WHandles);

// The return value from the WaitAny method is

// the array index of the Wait Handle that just

// finsihed running

switch (WHIndex)

{

case 0:

CustReader = CustCommand.EndExecuteReader(CustAsyncResult);

gvCustomers.DataSource = CustReader;

gvCustomers.DataBind();

break;

case 1:

OrdersReader =

OrdersCommand.EndExecuteReader(OrdersASyncResult);

gvOrders.DataSource = OrdersReader;

gvOrders.DataBind();

break;

}

}

// Closing connection

DBCon.Close();

}

</script>

posted on 2006-06-20 22:42 zhanqiangz(闲云野鹤) 阅读(1091) 评论(0)  编辑 收藏 所属分类: 翻译


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
博客园首页

新闻频道

社区

小组

博问

网摘

闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-06-20 22:57 编辑过
成果网帮您增加网站收入


相关链接:
 


<2006年6月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

导航

统计

公告

如转载本博客的相关资料敬请注明出处.谢谢合作!

与我联系

搜索

 

常用链接

留言簿(6)

我参与的团队

我的标签

随笔分类(51)

随笔档案(49)

文章分类(7)

文章档案(5)

收藏夹(3)

.NET

BizTalk

Design

JavaScript

My Blogs

Power Tools

Process Control

Search Engine

SQL Server

XML

积分与排名

最新评论

阅读排行榜

评论排行榜