前言 EAP,全称Event-based Asynchronous Pattern,基于事件的异步模式,它提供了一系列的事件声明与方法,用于实现异步模式的各个阶段。
典型的内置组件为BackgroundWorker组件,本文中我们将使用它来探寻此种模式的执行过程。
异步模型 相较于APM的复杂性,基于事件异步编程(EAP)简化了编程,并可以方便得在异步方法过程中通过增加事件来回调,与主线程交互。
基于事件的异步模式的功能
支持取消
支持IsBusy属性
支持完成通知
支持进度报告
支持返回增量结果
官方提供了AsyncCompletedEventArgs
、ProgressChangedEventArgs
等基础事件参数,可以直接使用或者继承使用,以及AsyncOperation
、AsyncOperationManager
操作线程上下文的帮助类
官方给出一个简单的组件System.ComponentModel.BackgroundWorker
如何实现异步
[MethodName
]Async
[MethodName
]Completed
[MethodName
]CancelAsync
EventArgs
命名规范
异步方法
对于同步方法创建对应的异步方法,以Async结尾。
1 2 3 4 5 6 7 8 9 10 11 public void Method (string param, object userState ){ } public void MethodAsync (string param, object userState ){ }
异步完成方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public delegate void MethodCompletedEventHandler (object sender, MethodCompletedEventArgs e ) ;public class MethodCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public MyReturnType Result { get ; } } public event MethodCompletedEventHandler MethodCompleted;public OnMethodCompleted (MethodCompletedEventArgs e ){ if (MethodCompleted != null ) { MethodCompleted(this ,e) } }
进度更新和增量结果
通常以ProgressChanged结尾,ProgressChangedEventArgs
是相对应得事件参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public delegate void ProgressChangedEventHandler (ProgressChangedEventArgs e ) ;public event MethodProgressChangeEventHandler MethodProgressChanged;public OnMethodProgressChanged (ProgressChangedEventArgs e ){ if (MethodProgressChanged != null ) { MethodProgressChanged(e) } }
相对应的取消方法
1 2 3 4 5 6 7 8 9 10 11 public void MethodCancelAsync (object userState ){ } public void CancelAsync (object userState ){ }
线程处理和上下文 同步方法最终是通过WorkerEventHandler委托方法执行,而委托底层 是采用线程池来执行。方法执行完再用AsyncOperation通知主线程或UI线程
注意:.NET Core已经不支持委托异步调用,EAP底层由Task承接异步操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 private delegate void WorkerEventHandler (AsyncOperation asyncOp ) ;private SendOrPostCallback onProgressChangeDelegate = new SendOrPostCallback(MethodProgressChange);private SendOrPostCallback onCompletedDelegate = new SendOrPostCallback(MethodComplete);public void Method (){ } private void MethodWoker (AsyncOperation asyncOp ){ Method(); asyncOp.Post(this .onProgressChangeDelegate); this .CompletionMethod(asyncOp); } private void MethodProgressChange (object state ){ var e = state as ProgressChangedEventArgs; OnMethodProgressChanged(e); } private void CompletionMethod (AsyncOperation asyncOp ){ var e = new MethodCompletedEventArgs(); asyncOp.PostOperationCompleted(onCompletedDelegate,e); } protected void MethodComplete (object operationState ){ var e = operationState as MethodCompletedEventArgs OnMethodCompleted (e ) ;} public void MethodAsync (){ AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(); WorkerEventHandler work = new WorkerEventHandler(MethodWoker); work.BeginInvoke(asyncOp); }
小结 相较于APM的编程,EAP逻辑思维上更顺畅和丝滑,虽然底层都是用委托来实现异步,没有APM那么晦涩难懂,但是编码量还是不少。