異步執行多個查詢並等待其中一個查詢完成
描述:下面有兩個SqlConnection一個用於獲取客戶信息,一個用於獲取訂單信息,它們使用同一字符串簡化該情景,在實際應用程序中,它們可以使用同一SQL Server或不同SQL Server
一旦該代碼異步執行兩個查詢,它會使用WaitHandle類的WaitAny方法等待兩個查詢中的任意一個完成,WaitAny方法接受WaitHandle的一個數組,並返回其操作已經完成的WaiHandle的索引,這裡的挑戰在於確定索引的含義,哪個查詢完成了?返回客戶消息的那個查詢還是返回訂單信息的那個查詢?
一種方法是硬編碼,數組中的第一項對應客戶查詢,數組中的第二項對應於訂單查詢,然後用Case或Switch代碼塊中松果WaitAny的返回值,以確定調用其EndExecuteReader方法的SqlCommand.
第二種方法是將一此信息附加狀態信息的傳遞給BeginExecuteReader方法,可以將諸如Customers和Orders等字符串傳遞給BeginExecuteReader方法.在此代碼段中,將實際SqlCommand對象傳遞給BeginExecuteReader方法.采用這一方法,可以通過IAsyncResult對象的AsyncState屬性使用SqlCommand對象,因此,當WaitAny調用返回時,我們訪問相應的IAsyncResutl對象,並且只是將AsyncState屬性轉換成SqlCommand,處理該結果並關閉SqlCommand的Connection
提示:以上代碼段在執行查詢時使用CommandBehavior.CloseConnecion.當在對ExecuteReader(或BeginExecuteReader)的調用中指定這一選項時,關閉所得的SqlDataReader還將關閉相應的SqlConnecion.使用CommandBehavior.CloseConnecion可以幫助編寫更可靠的代碼,特別是當使用SqlDataReader的 代碼不能訪問SqlConnection時
private void button15_Click(object sender, EventArgs e)
{
string strConn, strSQL;
SqlConnection cnCustomers, cnOrders;
SqlCommand cmdCustomers, cmdOrders;
IAsyncResult[] iasyncresults = new IAsyncResult[2];
WaitHandle[] waithandles = new WaitHandle[2];
strConn = @"Data Source=.\SQLExpress;" +
"Initial Catalog=Northwind;Integrated Security=True;" +
"Asynchronous Processing=True;";
//用戶客戶的連接
cnCustomers = new SqlConnection(strConn);
cnCustomers.Open();
//訂單的連接
cnOrders = new SqlConnection(strConn);
cnOrders.Open();
strSQL = "WAITFOR DELAY ''00:00:10''; " +
"SELECT TOP 10 CustomerID FROM Customers";
cmdCustomers = new SqlCommand(strSQL, cnCustomers);
//第一項客戶查詢
iasyncresults[0] = cmdCustomers.BeginExecuteReader(null, cmdCustomers,
CommandBehavior.
CloseConnection);
waithandles[0] = iasyncresults[0].AsyncWaitHandle;
strSQL = "WAITFOR DELAY ''00:00:05''; SELECT TOP 10 OrderID FROM Orders";
cmdOrders = new SqlCommand(strSQL, cnOrders);
//第二項訂單查詢
iasyncresults[1] = cmdOrders.BeginExecuteReader(null, cmdOrders,
CommandBehavior.
CloseConnection);
waithandles[1] = iasyncresults[1].AsyncWaitHandle;
for (int intCounter = 0; intCounter < waithandles.Length; intCounter++)
{
// 一旦該代碼異步執行兩個查詢會調用WaitHandle.WaitAny方法等待兩個查詢中的任意一個完成,
//WaitAny方法接受WaitHandle的一個數組,並返回其操作已經完成的WaitHandle的索引這裡在於確定索引的含義,哪個
//查詢完成了?返回客戶消息的那個查詢還是返回訂單的那個查詢?
int intIndex = WaitHandle.WaitAny(waithandles);
SqlCommand cmd = (SqlCommand)iasyncresults[intIndex].AsyncState;
Console.WriteLine(cmd.CommandText);
using (SqlDataReader rdr =
cmd.EndExecuteReader(iasyncresults[intIndex]))
{
while (rdr.Read())
Console.WriteLine(rdr[0]);
rdr.Close();
}
}
}