在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能够带来性能的提升,尤其对于那些高耗时的存储过程。