具体例子见MSDN:http://msdn.microsoft.com/zh-cn/library/bz33kx67(v=vs.100).aspx
首先采用类库编写组件,在窗口客户端引用组件类库。
组件的编写包括以下几部分:
1.在组件外部声明组件所要发布事件的委托,如进度和完成事件;
2.在组件内部声明组件所要发布的事件;
3.一般还要定义事件对应的输出和结果参数类EventArgs:如CalculatePrimeCompletedEventArgs;
4.基于时间的异步模式要用的AsyncOperation来跟踪和报告异步调用的进度,使用AsyncOperation.Post将进度和中间结果报告给客户端,使用AsyncOperation.PostOperationCompleted指示异步任务已完成,或取消挂起的任务,这两个函数都用到SendOrPostCallBack类型参数,该类型是一种在消息即将被调度到同步上下文是要执行的回调方法,该方法就是激发事件的起点,如onProgressReportDelegate,onCompletedDelegate,通过asyncOp.Post(this.onProgressReportDelegate, e);和 asyncOp.PostOperationCompleted(onCompletedDelegate, e);激发事件;
5.很多个客户端要调用该组件,所以组件中要建立一个列表的东西保存管理调用它的这些个客户端们,该示例中采用的是一个字典类HybridDictionary保存这些客户端,字典的键是一个唯一标识码GUID,值是异步操作类AsyncOperation,值得说明的是每个异步操作类相当于一个线程,要有一个唯一标识码GUID,避免错乱。
6.繁重计算任务的方法函数,如CalculateWorker(),BulidPrimeNumberList(),IsPrime(),就像“使用 Visual C# 创作简单的多线程组件”一样,计算函数中触发事件,如CalculateWorker()最后调用完成方法this.CompletionMethod();进而触发完成事件asyncOp.PostOperationCompleted(onCompletedDelegate, e);BuildPrimeNumberList()触发进度报告事件asyncOp.Post(this.onProgressReportDelegate, e); 另外值得说明的是为何要通过完成方法CompletionMethod激发完成事件,因为计算完成时不像报告进度那样只激发事件就行了,它还要做更多工作:计算完成,证明该客户端调用线程池里的线程计算任务已经完成了,所以要在统计字典里把该客户端给清除掉;第二个是事件对应参数的生成,这是必不可少的。
7.“实现公共事件”就是最终调用组件中event定义的事件:ProgressChanged; CalculatePrimeCompleted。
8. 最后的“实现启动和取消方法”是供客户端调用组件的接口,其中实现启动方法CalculatePrimeAsync类似于多线程组件中的创建并启动多线程函数的功能,只是这里不用我们创建多线程,我们直接调用线程池里的线程就可以了。使用工作线程池的方法是首先定义一个委托delegate调用一个要异步计算的方法(本例是CalculateWorker),该委托在组件中内部调动,设为私有;接下来使用delegate.BeginInvoke()发起一个异步调用。这样就完成了一个方法的异步调用。在此之前还有两步工作要做,一是创建一个异步操作类AsyncOperation,它是委托的一个参数,二是把启动异步操作的客户端加入的字典里面。
客户端的思路和“使用 Visual C# 创作简单的多线程组件”客户端的思路类似,在这里对以下几点做下巩固:
1.添加事件的订阅,如this.primeNumberCalculator1.CalculatePrimeCompleted +=
new CalculatePrimeCompletedEventHandler(
primeNumberCalculator1_CalculatePrimeCompleted);
2.完成事件的处理包括三种情况:取消,错误,正常完成;