在asp.net中雖然可以使用異步命令,但是不應盲目使用。來看兩種異步命令的使用場景。第一個場景是多條SQL語句的並行執行,可以面向單臺數據庫服務器,也可以是多臺。
假設有個頁面要顯示某個客戶的個人信息以及會計信息。前一部分來自客戶端數據庫,而後一部分則來自會計數據庫,我們可以同時發起兩個查詢,使他們在兩臺計算機上並行執行,從而真正地利用並行機制。
protected void btnQuery_Click(object sender, EventArgs e)
{
string custID = CustomerList.SelectedValue;
using (SqlConnection conn1 = new SqlConnection())
using (SqlConnection conn2 = new SqlConnection())
{
//開啓第一個查詢
SqlCommand cmd1 = new SqlCommand(CustomerInfoCmd, conn1);
cmd1.Parameters.Add("@customerid", SqlDbType.Char, 5).Value = custID;
conn1.Open();
IAsyncResult arCustomerInfo = cmd1.BeginExecuteReader();
//開啓第二個查詢
SqlCommand cmd2 = new SqlCommand(CustomerInfoCmd, conn2);
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.Parameters.Add("@customerid", SqlDbType.Char, 5).Value = custID;
conn2.Open();
IAsyncResult arOrdersInfo = cmd2.BeginExecuteReader();
//準備等待對象同步跟進
WaitHandle[] handles = new WaitHandle[2];
handles[0] = arCustomerInfo.AsyncWaitHandle;
handles[1] = arOrdersInfo.AsyncWaitHandle;
SqlDataReader reader;
//等到所有命令終止(5秒以內)
for (int i = 0; i < 2; i++)
{
StringBuilder builder = new StringBuilder();
int index = WaitHandle.WaitAny(handles, 5000, false);
if (index == WaitHandle.WaitTimeout)
{
throw new Exception("超時!!!");
}
if (index == 0)//客戶信息
{
reader = cmd1.EndExecuteReader(arCustomerInfo);
if (!reader.Read())
{
continue;
}
builder.AppendFormat("{0}<br>", reader["companyname"]);
builder.AppendFormat("{0}<br>", reader["adress"]);
builder.AppendFormat("{0}<br>", reader["country"]);
info.Text = builder.ToString();
reader.Close();
}
if (index==1)//訂單信息
{
reader = cmd2.EndExecuteReader(arOrdersInfo);
gridOrders.DataSource = reader;
gridOrders.DataBind();
reader.Close();
}
}
}
}
該頁面同時發起了兩個命令,然後等待第一個命令終止。兩個IAsyncResult的AsyncWaitHandle對象存儲在一個數組中,並傳到了WaitHandle類的WaitAny方法中。若其中任意一個終止,WaitAny便會發出通知,外圍的for語句會重複這種等待,直到所有掛起的命令都終止。選擇WaitAll 方法更簡單一些。在這種情況下,我們可以在所有結果集都就緒時進行處理。用WaitAny能夠帶來性能的提升,尤其對於那些高耗時的存儲過程。