http://www.cnblogs.com/fish-li/archive/2011/10/23/2222013.html
四、基于事件的异步模式(设计层面)
基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合。该异步模式具有以下优点:
· “在后台”执行耗时任务(例如下载和数据库 操作),但不会中断您的应用程序。
· 同时执行多个操作,每个操作完成时都会接到通知(在通知中可以区分是完成了哪个操作)。
· 等待资源变得可用,但不会停止(“挂起”)您的应用程序。
· 使用熟悉的事件和委托模型与挂起的异步操作通信。
对于相对简单的应用程序可以直接用 .Net 2.0 新增的 BackgroundWorker 组件来很方便的实现,对于更复杂的异步应用程序则需要自己实现一个符合基于事件的C#异步编程模式的类。在实现基于事件的异步模式的设计前,需要了解基于事件的异步模式的实现原理是什么。基于事件的异步模式需要以下三个类型的帮助。
AsyncOperation :提供了对异步操作的生存期进行跟踪的功能,包括操作进度通知和操作完成通知,并确保在正确的线程或上下文中调用客户端的事件处理程序。
public void Post(SendOrPostCallback d,Object arg);
public void PostOperationCompleted(SendOrPostCallback d,Object arg);
通过在异步辅助代码中调用Post方法把进度和中间结果报告给用户,如果是取消异步任务或提示异步任务已完成,则通过调用PostOperationCompleted方法结束异步操作的跟踪生命期。在PostOperationCompleted方法调用后,AsyncOperation对象变得不再可用,再次访问将引发异常。在此有个问题:在该异步模式中,通过AsyncOperation的Post函数来通知进度的时候,是如何使SendOrPostCallback委托在UI线程上执行的? 针对该问题下文有具体分析。
AsyncOperationManager :为AsyncOperation对象的创建提供了便捷方式,通过CreateOperation方法可以创建多个AsyncOperation实例,实现对多个异步操作进行跟踪。
WindowsFormsSynchronizationContext :该类继承自SynchronizationContext类型,提供 Windows 窗体应用程序模型的同步上下文。该类型是基于事件异步模式通信的核心。之所以说该类型是基于事件异步模式的通信核心,是因为该类型解决了“保证SendOrPostCallback委托在UI线程上执行 ”的问题。它是如何解决的?请看AsyncOperation类型的Post方法的实现:
public void Post(SendOrPostCallback d, object arg) { this .VerifyNotCompleted(); this .VerifyDelegateNotNull(d); this .syncContext.Post(d, arg); }
在AsyncOperation类型的Post方法中,直接调用了SynchronizationContext类型的Post方法,再看该Post方法的实现:
public override void Post(SendOrPostCallback d, object state) { if ( this .controlToSendTo != null ) { this .controlToSendTo.BeginInvoke(d, new object [] { state }); } }
有以上三个类型(AsyncOpertion,AsyncOperationManager和SynchronizationContext)作为基础,实现基于事件的异步模式的进度通知和完成通知就轻松多了。下面用一个基于事件的异步模型的例子来结束本文章。
using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Collections.Specialized; using System.Threading; namespace test { public delegate void Work1ProgressChangedEventHandler( object sender, Work1ProgressChangedEventArgs e); public delegate void Work1CompletedEventHandler( object sender, Work1CompletedEventArgs e); public class BasedEventAsyncWorker { private delegate void WorkerEventHandler( int maxNumber, AsyncOperation asyncOp); private HybridDictionary userStateToLifetime = new HybridDictionary(); public BasedEventAsyncWorker() { } #region DoWork1的基于事件的异步调用 public void DoWork1Async( object userState, int maxNumber) { AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(userState); lock (userStateToLifetime.SyncRoot) { if (userStateToLifetime.Contains(userState)) { throw new ArgumentException( "userState parameter must be unique" , "userState" ); } userStateToLifetime[userState] = asyncOp; } WorkerEventHandler workerDelegate = new WorkerEventHandler(DoWork1); workerDelegate.BeginInvoke(maxNumber, asyncOp, null , null ); } private void DoWork1( int maxNumber, AsyncOperation asyncOp) { Exception e = null ; if (!TaskCanceled(asyncOp.UserSuppliedState)) { try { int n = 0; int percentage = 0; while (n < maxNumber && !TaskCanceled(asyncOp.UserSuppliedState)) { Thread.Sleep(100); percentage = (int )(( float )n / ( float )maxNumber * 100); Work1ProgressChangedEventArgs progressChanageArgs = new Work1ProgressChangedEventArgs(maxNumber, percentage, asyncOp.UserSuppliedState); asyncOp.Post(new SendOrPostCallback(Work1ReportProgressCB), progressChanageArgs); n++; } } catch (Exception ex) { e = ex; } } this .Work1Complete(e, TaskCanceled(asyncOp.UserSuppliedState), asyncOp); } private void Work1Complete(Exception exception, bool canceled, AsyncOperation asyncOp) { if (!canceled) { lock (userStateToLifetime.SyncRoot) { userStateToLifetime.Remove(asyncOp.UserSuppliedState); } } Work1CompletedEventArgs e = new Work1CompletedEventArgs(exception, canceled, asyncOp.UserSuppliedState); asyncOp.PostOperationCompleted(new SendOrPostCallback(Work1CompleteCB), e); } private void Work1ReportProgressCB( object state) { Work1ProgressChangedEventArgs e = state as Work1ProgressChangedEventArgs; OnWork1ProgressChanged(e); } private void Work1CompleteCB( object state) { Work1CompletedEventArgs e = state as Work1CompletedEventArgs; OnWork1Completed(e); } #region Work1的进度通知和任务完成的事件 public event Work1ProgressChangedEventHandler Work1ProgressChanged; protected virtual void OnWork1ProgressChanged(Work1ProgressChangedEventArgs e) { Work1ProgressChangedEventHandler temp = this .Work1ProgressChanged; if (temp != null ) { temp(this , e); } } public event Work1CompletedEventHandler Work1Completed; protected virtual void OnWork1Completed(Work1CompletedEventArgs e) { Work1CompletedEventHandler temp = this .Work1Completed; if (temp != null ) { temp(this , e); } } #endregion #endregion public void CancelAsync( object userState) { AsyncOperation asyncOp = userStateToLifetime[userState] as AsyncOperation; if (asyncOp != null ) { lock (userStateToLifetime.SyncRoot) { userStateToLifetime.Remove(userState); } } } private bool TaskCanceled( object userState) { return (userStateToLifetime[userState] == null ); } } public class Work1ProgressChangedEventArgs :ProgressChangedEventArgs { private int totalWork = 1; public Work1ProgressChangedEventArgs( int totalWork, int progressPercentage, object userState) : base (progressPercentage, userState) { this .totalWork = totalWork; } public int TotalWork { get { return totalWork; } } } public class Work1CompletedEventArgs : AsyncCompletedEventArgs { public Work1CompletedEventArgs(Exception e, bool canceled, object state) : base (e, canceled, state) { } } }