可以用3种不同的方式处理异步命令。一种方式是启动异步进程,再选择 IAsyncResult对象,看看进程何时完成。第二种方式是在开始异步进程时提供一个回调方法。这种方式可以并行执行其他任务。异步进程完成时,就触发回调方法进行清理,并通知程序的其他部分该异步进程已完成。第三种也是最好的方法就是把一个等待句柄关联到异步进程上,使用这种方式,可以启动需要的所有异步进程,等待全部或部分进程的完成,以便对它们进行相应的处理。
Poll方式
using System.Data; using System.Data.SqlClient; using SYstem.Configuration; public class SampleClass { protocted void Page_Load(object sender,EventArgs e) { SqlConnection DBCon; SqlCommand Command = new SqlCommand(); SqlDataAdapter OrderReader; IAsyncResult AsyncResult; DBCon = new SqlConnection(); DBCon.ConnectionString = ConfigurationManger.ConnectionStrings["AspNetProvider"]; Command.CommandText = "SELECT TOP 5 Customers.*,Orders.* FROM Orders,Customers WHERE Orders.CustomerID = Customers.CustomerID ORDER BY ustomers.CompanyName"; Command.CommandType = CommandType.Text; Command.Connection = DBCon; DBCon.Open(); AsyncResult = Command.BeginExecuteReader(); while(!AsyncResult.IsCompleted) { System.Threading.Thread.Sleep(10); } OrderReader = Command.EndExecuteReader(AsyncResult); // To do Anything You Want DBCon.Close(); } }
它首先调用BeginExecuteReader,启动异步进程。之后,使用while循环等待进程的完成。在等待时,主线程全检查异步进程的状态,然后休眠10毫秒。进程完成后,就使用EndExecuteReader方法提取结果。
如果在while循环上设置一个断点,就可以看到代码在调用BeiginExecuteReader方法后会继续执行。之后代码继续循环,直到异步进程完成为止。
Wait方式
3种方式中最好的一种不是Poll方式,也不是回调方式,而是Wait方式。该方式提供的灵活性最大、效率最高,但有点复杂。使用这种方式,可以编写代码,启动多个异步进程,等待全部或部分进程的完成。这种方式允许只等待互相依赖的进程,然后继续执行不互相依赖的进程。按照其设计,这种方式需要仔细考虑异步进程。必须认真选择出以并行方式运行的异步进程,最重要的是,确定不同的进程如何相互依赖。这种方式的复杂性在于,需要理解其中的细节,并设计出相应的代码。最终结果一般是,非常简洁的代码设计能最大限度地利用同步和异步处理模型。
using System.Data; using System.Data.SqlClient; using System.Data.Configuration; public class SampleClass { 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(); DB.ConnectionStrings = ConfigurationManager.ConnectionStrings["AspNetProvider"]; Command.CommandText = "SELECT TOP 5 Customers.*,Orders.* FROM Orders,Customers WHERE Orders.CustomerID = Customers.CustomerID ORDER BY ustomers.CompanyName"; Command.CommandType = CommandType.Text; Command.Connection = DBCon; DBCon.Open(); AsyncResult = Command.BeginExecuteReader(); WHandle = AsyncResult.AsyncWaitHandle; if(WHandle.WaitOne() == true) { OrdersReader = Command.EndExecuteReader(AsyncResult); // Todo: DBCon.Close(); } else { // When Execute On Timeouts EventHandler } } }如果设置一个断点,单步执行这段代码,程序就会在WHandle.WaitOne方法调用处停止执行。在异步进程完成后,程序会自动恢复执行。
回调方式
它首先调用BeginExecuteReader方法,给它传送回调委托,以启动异步进程。不需要进一步的处理,该方法在异步进程启动后结束。触发回调委托,以启动异步进程。不需要进一步的处理,该方法在异步进程启动后结束。
public class SampleClass { protected void Page_Load(object sender,EventArgs e) { SqlConnection DBCon; SqlCommand Command = new SqlCommand(); SqlDataReader OrdersReader; IAsyncResult AsyncResult; DBCon = new SqlConnection(); DB.ConnectionStrings = ConfigurationManager.ConnectionStrings["AspNetProvider"]; Command.CommandText = "SELECT TOP 5 Customers.*,Orders.* FROM Orders,Customers WHERE Orders.CustomerID = Customers.CustomerID ORDER BY ustomers.CompanyName"; Command.CommandType = CommandType.Text; Command.Connection = DBCon; DBCon.Open(); AsyncResult = Command.BeginExecuteReader(new AsyncCallback(CBMethod),CommandBehavior.CloseConnection); } public void CBMethod(SQLAsyncResult ar) { SqlDataReader OrdersReader;; OrdersReader = ar.EndExecuteReader(ar); // Todo: } }回调方式可以在代码的另一个部分处理命令执行的结果。当命令执行的时间比较长,且需要在不待到命令执行完毕后就回应用户时,可以使用这种方式。
取消异步处理
异步进程需要的时间常常比希望的长。为了避免这个问题,可以给用户提供一个选项来取消该进程,而不等待结果。取消异步进程只需在相应的Command对象上调用Cancel方法即可。这个方法没有返回值。为了回退已由Command对象完成的工作,必须在执行查询前,给Command对象提供一个定制事务。也可以自己处理回退或提交进程。