一个简化的异步调用模式
我经常使用一项技术来减少创建异步调用时的复杂度和代码量,那就是把线程切换和委托的实现放入一个中间类中。这就使得我们从用户界面类中进行异步调用时,不用再去考虑什么线程和委托的问题。我把这项技术叫做自动回调。使用这项技术,上面的样例可以进行如下改进:
private void SomeUIEvent( object sender, EventArgs e ) { // Start retrieving the customer data. _serviceAgent.BeginGetCustomerData( "Joe Bloggs" ); }
当Web服务访问完成后,以下的方法就会自动被调用:
private void GetCustomerDataCompleted( DataSet customerData ) { // This method will be called on the UI thread. // Update the user interface. _dataGrid.DataSource = customerData; }
回调函数的名称由原始异步调用的名称来决定(因此就不再需要创建和传递委托了),并且可以保证被正确的线程所调用(也就不再需要使用Control.Invoke了),这些方法都很简单并且不容易出错。
天下没有免费的午餐,实现这个简单模型的神奇代码是需要我们来编写的。下面所列的就是被编写进ServiceAgent类中的这些代码:
public class ServiceAgent : AutoCallbackServiceAgent { private CustomerWebService _proxy; // Declare a delegate to describe the autocallback // method signature. private delegate void GetCustomerDataCompletedCallback( DataSet customerData ); public ServiceAgent( object callbackTarget ) : base( callbackTarget ) { // Create the Web service proxy object. _proxy = new CustomerWebService(); } public void BeginGetCustomerData( string customerId ) { _proxy.BeginGetCustomerData( customerId, new AsyncCallback( GetCustomersCallback ), null ); } private void GetCustomerDataCallback( IAsyncResult ar ) { DataSet customerData = _proxy.EndGetCustomerData( ar ); InvokeAutoCallback( "GetCustomerDataCompleted", new object[] { customerData }, typeof( GetCustomersCompletedCallback ) ); } }
这个样例中服务代理类的代码是简单容易的,而且完全可以重用,我们所要做的就是给WinForm类编写一套类似的通用代码。我们有效的提升了线程管理工作的重要性,并且把它同编写后台异步调用对象代码的工作以及编写前台客户端代码的工作分离了开来。
(编辑:aniston)
|