C#中的异步调用及异步设计模式(三)——基于事件的异步模式

四、基于事件的异步模式(设计层面)

基于事件的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方法的实现:

/// <summary> /// AsyncOperation类型的Post方法的实现 /// </summary> public void Post(SendOrPostCallback d, object arg) { this.VerifyNotCompleted(); this.VerifyDelegateNotNull(d); this.syncContext.Post(d, arg); }


在AsyncOperation类型的Post方法中,直接调用了SynchronizationContext类型的Post方法,再看该Post方法的实现:

/// <summary> /// WindowsFormsSynchronizationContext类型的Post方法的实现 /// </summary> public override void Post(SendOrPostCallback d, object state) { if (this.controlToSendTo != null) { this.controlToSendTo.BeginInvoke(d, new object[] { state }); //此处保证了SendOrPostCallBack委托在UI线程上执行 } }


有以上三个类型(AsyncOpertion,AsyncOperationManager和SynchronizationContext)作为基础,实现基于事件的异步模式的进度通知和完成通知就轻松多了。下面用一个基于事件的异步模型的例子来结束本文章。

using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Collections.Specialized; using System.Threading; namespace test { /// <summary> /// 任务1的进度通知代理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public delegate void Work1ProgressChangedEventHandler(object sender, Work1ProgressChangedEventArgs e); /// <summary> /// 任务1的进度通知参数 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> 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); //userStateToLifetime有可能会同时被多线程访问,在此需要lock进行同步处理 lock (userStateToLifetime.SyncRoot) { if (userStateToLifetime.Contains(userState)) { throw new ArgumentException( "userState parameter must be unique", "userState"); } userStateToLifetime[userState] = asyncOp; } //异步开始任务1 WorkerEventHandler workerDelegate = new WorkerEventHandler(DoWork1); workerDelegate.BeginInvoke(maxNumber, asyncOp, null, null); } private void DoWork1(int maxNumber, AsyncOperation asyncOp) { Exception e = null; //判断该userState的任务仍在处理中 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); //任务1的进度通知 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); //调用 PostOperationCompleted 方法来结束异步操作的生存期。 //为某个特定任务调用此方法后,再调用其相应的 AsyncOperation 对象会引发异常。 } 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 /// <summary> /// 取消指定userState的任务执行 /// </summary> /// <param name="userState"></param> public void CancelAsync(object userState) { AsyncOperation asyncOp = userStateToLifetime[userState] as AsyncOperation; if (asyncOp != null) { lock (userStateToLifetime.SyncRoot) { userStateToLifetime.Remove(userState); } } } /// <summary> /// 判断指定userState的任务是否已经被结束。返回值:true 已经结束; false 还没有结束 /// </summary> /// <param name="userState"></param> /// <returns></returns> 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; } /// <summary> /// Work1的总工作量 /// </summary> public int TotalWork { get { return totalWork; } } } public class Work1CompletedEventArgs : AsyncCompletedEventArgs { public Work1CompletedEventArgs(Exception e, bool canceled, object state) : base(e, canceled, state) { } } }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值