異步編程:基于事件的異步編程模式(EMP)
上一篇,我給大家介紹了“.NET1.0中基于IAsyncResult設(shè)計(jì)模式的異步編程模型(APM)”,它使用System.Threading命名空間的類(lèi)來(lái)構(gòu)造多線程應(yīng)用程序。然而要想有效地使用這些工具類(lèi),需要有豐富的使用多線程軟件工程的經(jīng)驗(yàn)。對(duì)于相對(duì)簡(jiǎn)單的多線程應(yīng)用程序,BackgroundWorker組件提供了一個(gè)簡(jiǎn)單的解決方案。對(duì)于更復(fù)雜的異步應(yīng)用程序,可以考慮實(shí)現(xiàn)一個(gè)符合基于事件的異步模式的類(lèi)。
使用支持此模式的類(lèi),您將能夠:
1) 異步執(zhí)行耗時(shí)的任務(wù)。
2) 獲得進(jìn)度報(bào)告和增量結(jié)果。
3) 支持耗時(shí)任務(wù)的取消。
4) 獲得任務(wù)的結(jié)果值或異常信息。
5) 更復(fù)雜:支持同時(shí)執(zhí)行多個(gè)異步操作、進(jìn)度報(bào)告、增量結(jié)果、取消操作、返回結(jié)果值或異常信息。
源碼下載:異步編程:基于事件的異步模型(EAP).rar
為了實(shí)現(xiàn)基于事件的異步模式,我們必須先理解兩個(gè)重要的幫助器類(lèi):
AsyncOperationManager和AsyncOperation
AsyncOperationManager類(lèi)和AsyncOperation類(lèi)是System.ComponentModel命名空間為我們提供了兩個(gè)重要幫助器類(lèi)。在基于事件的異步模式封裝標(biāo)準(zhǔn)化的異步功能中,它確保你的異步操作支持在各種應(yīng)用程序模型(包括 ASP.NET、控制臺(tái)應(yīng)用程序和 Windows 窗體應(yīng)用程序)的適當(dāng)“線程或上下文”調(diào)用客戶(hù)端事件處理程序。
AsyncOperationManager類(lèi)和AsyncOperation類(lèi)的API如下:
- // 為支持異步方法調(diào)用的類(lèi)提供并發(fā)管理。此類(lèi)不能被繼承。
- public static class AsyncOperationManager
- {
- // 獲取或設(shè)置用于異步操作的同步上下文。
- public static SynchronizationContext SynchronizationContext { get; set; }
- // 返回可用于對(duì)特定異步操作的持續(xù)時(shí)間進(jìn)行跟蹤的AsyncOperation對(duì)象。
- // 參數(shù):userSuppliedState:
- // 一個(gè)對(duì)象,用于使一個(gè)客戶(hù)端狀態(tài)(如任務(wù) ID)與一個(gè)特定異步操作相關(guān)聯(lián)。
- public static AsyncOperation CreateOperation(object userSuppliedState)
- {
- return AsyncOperation.CreateOperation(userSuppliedState,SynchronizationContext);
- }
- }
- // 跟蹤異步操作的生存期。
- public sealed class AsyncOperation
- {
- // 構(gòu)造函數(shù)
- private AsyncOperation(object userSuppliedState, SynchronizationContext syncContext);
- internal static AsyncOperation CreateOperation(object userSuppliedState
- , SynchronizationContext syncContext);
- // 獲取傳遞給構(gòu)造函數(shù)的SynchronizationContext對(duì)象。
- public SynchronizationContext SynchronizationContext { get; }
- // 獲取或設(shè)置用于唯一標(biāo)識(shí)異步操作的對(duì)象。
- public object UserSuppliedState { get; }
- // 在各種應(yīng)用程序模型適合的線程或上下文中調(diào)用委托。
- public void Post(SendOrPostCallback d, object arg);
- // 結(jié)束異步操作的生存期。
- public void OperationCompleted();
- // 效果同調(diào)用 Post() + OperationCompleted() 方法組合
- public void PostOperationCompleted(SendOrPostCallback d, object arg);
- }
先分析下這兩個(gè)幫助器類(lèi):
1. AsyncOperationManager是靜態(tài)類(lèi)。靜態(tài)類(lèi)是密封的,因此不可被繼承。倘若從靜態(tài)類(lèi)繼承會(huì)報(bào)錯(cuò)“靜態(tài)類(lèi)必須從 Object 派生”。(小常識(shí),以前以為密封類(lèi)就是 sealed 關(guān)鍵字)
2. AsyncOperationManager為支持異步方法調(diào)用的類(lèi)提供并發(fā)管理,該類(lèi)可正常運(yùn)行于 .NET Framework 支持的所有應(yīng)用程序模式下。
3. AsyncOperation實(shí)例提供對(duì)特定異步任務(wù)的生存期進(jìn)行跟蹤??捎脕?lái)處理任務(wù)完成通知,還可用于在不終止異步操作的情況下發(fā)布進(jìn)度報(bào)告和增量結(jié)果(這種不終止異步操作的處理是通過(guò)AsyncOperation的 Post() 方法實(shí)現(xiàn))。
4. AsyncOperation類(lèi)有一個(gè)私有的構(gòu)造函數(shù)和一個(gè)內(nèi)部CreateOperation() 靜態(tài)方法。由AsyncOperationManager類(lèi)調(diào)用AsyncOperation.CreateOperation() 靜態(tài)方法來(lái)創(chuàng)建AsyncOperation實(shí)例。
5. AsyncOperation類(lèi)是通過(guò)SynchronizationContext類(lèi)來(lái)實(shí)現(xiàn)在各種應(yīng)用程序的適當(dāng)“線程或上下文”調(diào)用客戶(hù)端事件處理程序。
- // 提供在各種同步模型中傳播同步上下文的基本功能。
- public class SynchronizationContext
- {
- // 獲取當(dāng)前線程的同步上下文。
- public static SynchronizationContext Current { get; }
- // 當(dāng)在派生類(lèi)中重寫(xiě)時(shí),響應(yīng)操作已開(kāi)始的通知。
- public virtual void OperationStarted();
- // 當(dāng)在派生類(lèi)中重寫(xiě)時(shí),將異步消息調(diào)度到一個(gè)同步上下文。
- public virtual void Post(SendOrPostCallback d, object state);
- // 當(dāng)在派生類(lèi)中重寫(xiě)時(shí),響應(yīng)操作已完成的通知。
- public virtual void OperationCompleted();
- ……
- }
a) 在AsyncOperation構(gòu)造函數(shù)中調(diào)用SynchronizationContext的OperationStarted() ;
b) 在AsyncOperation的 Post() 方法中調(diào)用SynchronizationContext的Post() ;
c) 在AsyncOperation的OperationCompleted()方法中調(diào)用SynchronizationContext的OperationCompleted();
6. SendOrPostCallback委托簽名:
- // 表示在消息即將被調(diào)度到同步上下文時(shí)要調(diào)用的方法。
- public delegate void SendOrPostCallback(object state);
#p#
基于事件的異步模式的特征
1. 基于事件的異步模式可以采用多種形式,具體取決于某個(gè)特定類(lèi)支持操作的復(fù)雜程度:
1) 最簡(jiǎn)單的類(lèi)可能只有一個(gè) ***Async方法和一個(gè)對(duì)應(yīng)的 ***Completed 事件,以及這些方法的同步版本。
2) 復(fù)雜的類(lèi)可能有若干個(gè) ***Async方法,每種方法都有一個(gè)對(duì)應(yīng)的 ***Completed 事件,以及這些方法的同步版本。
3) 更復(fù)雜的類(lèi)還可能為每個(gè)異步方法支持取消(CancelAsync()方法)、進(jìn)度報(bào)告和增量結(jié)果(ReportProgress() 方法+ProgressChanged事件)。
4) 如果您的類(lèi)支持多個(gè)異步方法,每個(gè)異步方法返回不同類(lèi)型的數(shù)據(jù),您應(yīng)該:
a) 將您的增量結(jié)果報(bào)告與您的進(jìn)度報(bào)告分開(kāi)。
b) 使用適當(dāng)?shù)腅ventArgs為每個(gè)異步方法定義一個(gè)單獨(dú)的 ***ProgressChanged事件以處理該方法的增量結(jié)果數(shù)據(jù)。
5) 如果類(lèi)不支持多個(gè)并發(fā)調(diào)用,請(qǐng)考慮公開(kāi)IsBusy屬性。
6) 如要異步操作的同步版本中有 Out 和 Ref 參數(shù),它們應(yīng)做為對(duì)應(yīng) ***CompletedEventArgs的一部分,eg:
- public int MethodName(string arg1, ref string arg2, out string arg3);
- public void MethodNameAsync(string arg1, string arg2);
- public class MethodNameCompletedEventArgs : AsyncCompletedEventArgs
- {
- public int Result { get; };
- public string Arg2 { get; };
- public string Arg3 { get; };
- }
2. 如果你的組件要支持多個(gè)異步耗時(shí)的任務(wù)并行執(zhí)行。那么:
1) 為***Async方法多添加一個(gè)userState對(duì)象參數(shù)(此參數(shù)應(yīng)當(dāng)始終是***Async方法簽名中的最后一個(gè)參數(shù)),用于跟蹤各個(gè)操作的生存期。
2) 注意要在你構(gòu)建的異步類(lèi)中維護(hù)一個(gè)userState對(duì)象的集合。使用 lock 區(qū)域保護(hù)此集合,因?yàn)楦鞣N調(diào)用都會(huì)在此集合中添加和移除userState對(duì)象。
3) 在***Async方法開(kāi)始時(shí)調(diào)用AsyncOperationManager.CreateOperation并傳入userState對(duì)象,為每個(gè)異步任務(wù)創(chuàng)建AsyncOperation對(duì)象,userState存儲(chǔ)在AsyncOperation的UserSuppliedState屬性中。在構(gòu)建的異步類(lèi)中使用該屬性標(biāo)識(shí)取消的操作,并傳遞給CompletedEventArgs和ProgressChangedEventArgs參數(shù)的UserState屬性來(lái)標(biāo)識(shí)當(dāng)前引發(fā)進(jìn)度或完成事件的特定異步任務(wù)。
4) 當(dāng)對(duì)應(yīng)于此userState對(duì)象的任務(wù)引發(fā)完成事件時(shí),你構(gòu)建的異步類(lèi)應(yīng)將AsyncCompletedEventArgs.UserState對(duì)象從集合中刪除。
3. 注意:
1) 確保 ***EventArgs類(lèi)特定于***方法。即當(dāng)使用 ***EventArgs類(lèi)時(shí),切勿要求開(kāi)發(fā)人員強(qiáng)制轉(zhuǎn)換類(lèi)型值。
2) 確保始終引發(fā)方法名稱(chēng)Completed 事件。成功完成、異?;蛘呷∠麜r(shí)應(yīng)引發(fā)此事件。任何情況下,應(yīng)用程序都不應(yīng)遇到這樣的情況:應(yīng)用程序保持空閑狀態(tài),而操作卻一直不能完成。
3) 確??梢圆东@異步操作中發(fā)生的任何異常并將捕獲的異常指派給 Error 屬性。
4) 確保 ***CompletedEventArgs 類(lèi)將其成員公開(kāi)為只讀屬性而不是字段,因?yàn)樽侄螘?huì)阻止數(shù)據(jù)綁定。eg:public MyReturnType Result { get; }
5) 在構(gòu)建 ***CompletedEventArgs 類(lèi)屬性時(shí),通過(guò)this.RaiseExceptionIfNecessary() 方法確保屬性值被正確使用。Eg:
- public int MethodName(string arg1, ref string arg2, out string arg3);
- public void MethodNameAsync(string arg1, string arg2);
- public class MethodNameCompletedEventArgs : AsyncCompletedEventArgs
- {
- public int Result { get; };
- public string Arg2 { get; };
- public string Arg3 { get; };
- }
2. 如果你的組件要支持多個(gè)異步耗時(shí)的任務(wù)并行執(zhí)行。那么:
1) 為***Async方法多添加一個(gè)userState對(duì)象參數(shù)(此參數(shù)應(yīng)當(dāng)始終是***Async方法簽名中的最后一個(gè)參數(shù)),用于跟蹤各個(gè)操作的生存期。
2) 注意要在你構(gòu)建的異步類(lèi)中維護(hù)一個(gè)userState對(duì)象的集合。使用 lock 區(qū)域保護(hù)此集合,因?yàn)楦鞣N調(diào)用都會(huì)在此集合中添加和移除userState對(duì)象。
3) 在***Async方法開(kāi)始時(shí)調(diào)用AsyncOperationManager.CreateOperation并傳入userState對(duì)象,為每個(gè)異步任務(wù)創(chuàng)建AsyncOperation對(duì)象,userState存儲(chǔ)在AsyncOperation的UserSuppliedState屬性中。在構(gòu)建的異步類(lèi)中使用該屬性標(biāo)識(shí)取消的操作,并傳遞給CompletedEventArgs和ProgressChangedEventArgs參數(shù)的UserState屬性來(lái)標(biāo)識(shí)當(dāng)前引發(fā)進(jìn)度或完成事件的特定異步任務(wù)。
4) 當(dāng)對(duì)應(yīng)于此userState對(duì)象的任務(wù)引發(fā)完成事件時(shí),你構(gòu)建的異步類(lèi)應(yīng)將AsyncCompletedEventArgs.UserState對(duì)象從集合中刪除。
3. 注意:
1) 確保 ***EventArgs類(lèi)特定于***方法。即當(dāng)使用 ***EventArgs類(lèi)時(shí),切勿要求開(kāi)發(fā)人員強(qiáng)制轉(zhuǎn)換類(lèi)型值。
2) 確保始終引發(fā)方法名稱(chēng)Completed 事件。成功完成、異常或者取消時(shí)應(yīng)引發(fā)此事件。任何情況下,應(yīng)用程序都不應(yīng)遇到這樣的情況:應(yīng)用程序保持空閑狀態(tài),而操作卻一直不能完成。
3) 確??梢圆东@異步操作中發(fā)生的任何異常并將捕獲的異常指派給 Error 屬性。
4) 確保 ***CompletedEventArgs 類(lèi)將其成員公開(kāi)為只讀屬性而不是字段,因?yàn)樽侄螘?huì)阻止數(shù)據(jù)綁定。eg:public MyReturnType Result { get; }
5) 在構(gòu)建 ***CompletedEventArgs 類(lèi)屬性時(shí),通過(guò)this.RaiseExceptionIfNecessary() 方法確保屬性值被正確使用。Eg:
- private bool isPrimeValue;
- public bool IsPrime
- {
- get
- {
- RaiseExceptionIfNecessary();
- return isPrimeValue;
- }
- }
所以,在***Completed事件處理程序中,應(yīng)當(dāng)總是先檢查 ***CompletedEventArgs.Error 和 ***CompletedEventArgs.Cancelled 屬性,然后再訪問(wèn)RunWorkerCompletedEventArgs.Result屬性。
#p#
BackgroundWorker組件
System.ComponentModel命名空間的BackgroundWorker組件為我們提供了一個(gè)簡(jiǎn)單的多線程應(yīng)用解決方案,它允許你在單獨(dú)的線程上運(yùn)行耗時(shí)操作而不會(huì)導(dǎo)致用戶(hù)界面的阻塞。但是,要注意它同一時(shí)刻只能運(yùn)行一個(gè)異步耗時(shí)操作(使用IsBusy屬性判定),并且不能跨AppDomain邊界進(jìn)行封送處理(不能在多個(gè)AppDomain中執(zhí)行多線程操作)。
1. BackgroundWorker組件
- public class BackgroundWorker : Component
- {
- public BackgroundWorker();
- // 獲取一個(gè)值,指示應(yīng)用程序是否已請(qǐng)求取消后臺(tái)操作。
- public bool CancellationPending { get; }
- // 獲取一個(gè)值,指示BackgroundWorker是否正在運(yùn)行異步操作。
- public bool IsBusy { get; }
- // 獲取或設(shè)置一個(gè)值,該值指示BackgroundWorker能否報(bào)告進(jìn)度更新。
- public bool WorkerReportsProgress { get; set; }
- // 獲取或設(shè)置一個(gè)值,該值指示BackgroundWorker是否支持異步取消。
- public bool WorkerSupportsCancellation { get; set; }
- // 調(diào)用RunWorkerAsync() 時(shí)發(fā)生。
- public event DoWorkEventHandlerDoWork;
- // 調(diào)用ReportProgress(System.Int32) 時(shí)發(fā)生。
- public event ProgressChangedEventHandlerProgressChanged;
- // 當(dāng)后臺(tái)操作已完成、被取消或引發(fā)異常時(shí)發(fā)生。
- public event RunWorkerCompletedEventHandlerRunWorkerCompleted;
- // 請(qǐng)求取消掛起的后臺(tái)操作。
- public void CancelAsync();
- // 引發(fā)ProgressChanged事件。percentProgress:范圍從 0% 到 100%
- public void ReportProgress(int percentProgress);
- // userState:傳遞到RunWorkerAsync(System.Object) 的狀態(tài)對(duì)象。
- public void ReportProgress(int percentProgress, object userState);
- // 開(kāi)始執(zhí)行后臺(tái)操作。
- public void RunWorkerAsync();
- // 開(kāi)始執(zhí)行后臺(tái)操作。argument:傳遞給DoWork事件的DoWorkEventArgs參數(shù)。
- public void RunWorkerAsync(object argument);
- }
2. 相應(yīng)的EventArgs類(lèi)
- ///1) System.EventArgs基類(lèi)
- // System.EventArgs是包含事件數(shù)據(jù)的類(lèi)的基類(lèi)。
- public class EventArgs
- {
- // 表示沒(méi)有事件數(shù)據(jù)的事件。
- public static readonly EventArgs Empty;
- public EventArgs();
- }
- ///2) DoWorkEventArgs類(lèi)
- // 為可取消的事件提供數(shù)據(jù)。
- public class CancelEventArgs : EventArgs
- {
- public CancelEventArgs();
- public CancelEventArgs(bool cancel);
- // 獲取或設(shè)置指示是否應(yīng)取消事件的值。
- public bool Cancel { get; set; }
- }
- // 為DoWork事件處理程序提供數(shù)據(jù)。
- public class DoWorkEventArgs : CancelEventArgs
- {
- public DoWorkEventArgs(object argument);
- // 獲取表示異步操作參數(shù)的值。
- public object Argument { get; }
- // 獲取或設(shè)置表示異步操作結(jié)果的值。
- public object Result { get; set; }
- }
- ///3) ProgressChangedEventArgs類(lèi)
- // 為ProgressChanged事件提供數(shù)據(jù)。
- public class ProgressChangedEventArgs : EventArgs
- {
- public ProgressChangedEventArgs(int progressPercentage, object userState);
- // 獲取異步任務(wù)的進(jìn)度百分比。
- public int ProgressPercentage { get; }
- // 獲取唯一的用戶(hù)狀態(tài)。
- public object UserState { get; }
- }
- ///4) RunWorkerCompletedEventArgs類(lèi)
- // 為MethodNameCompleted事件提供數(shù)據(jù)。
- public class AsyncCompletedEventArgs : EventArgs
- {
- public AsyncCompletedEventArgs();
- public AsyncCompletedEventArgs(Exception error, bool cancelled, object userState);
- // 獲取一個(gè)值,該值指示異步操作是否已被取消。
- public bool Cancelled { get; }
- // 獲取一個(gè)值,該值指示異步操作期間發(fā)生的錯(cuò)誤。
- public Exception Error { get; }
- // 獲取異步任務(wù)的唯一標(biāo)識(shí)符。
- public object UserState { get; }
- // 訪問(wèn) AsyncCompletedEventArgs 及其派生類(lèi)的屬性前調(diào)用此方法
- protected void RaiseExceptionIfNecessary()
- {
- if (this.Error != null)
- {
- throw new TargetInvocationException(……);
- }
- if (this.Cancelled)
- {
- throw new InvalidOperationException(……);
- }
- }
- }
- public class RunWorkerCompletedEventArgs : AsyncCompletedEventArgs
- {
- public RunWorkerCompletedEventArgs(object result, Exception error, bool cancelled);
- // 獲取表示異步操作結(jié)果的值。
- public object Result { get; }
- // 獲取表示用戶(hù)狀態(tài)的值。
- public object UserState { get; }
- }
示例代碼中包含了BackgroundWorker源代碼及對(duì)應(yīng)的使用示例,這里不粘貼代碼了,會(huì)導(dǎo)致篇幅更大。來(lái)個(gè)示例截圖吧:
示例分析:
1) 首先我們?yōu)锽ackgroundWorker組件注冊(cè)DoWork(異步操作)、ProgressChanged(進(jìn)度報(bào)告) 和RunWorkCompleted(完成通知)事件;
2) 設(shè)置WorkerSupportsCancellation和WorkerReportsProgress屬性為true,以聲明組件支持取消操作和進(jìn)度報(bào)告;
3) 使用RunWorkerAsync() 開(kāi)啟異步操作,通過(guò)IsBusy屬性判斷是否已經(jīng)有異步任務(wù)在執(zhí)行;
4) 使用CancelAsync() 方法取消異步操作,但要注意:
a) 它僅僅是將BackgroudWorker.CancellationPending屬性設(shè)置為true。需要在具體DoWork事件中不斷檢查BackgroudWorker.CancellationPending來(lái)設(shè)置DoWorkEventArgs的Cancel屬性。
b) DoWork事件處理程序中的代碼有可能在發(fā)出取消請(qǐng)求時(shí)完成其工作,輪詢(xún)循環(huán)可能會(huì)錯(cuò)過(guò)設(shè)置為 true 的CancellationPending屬性。在這種情況下,即使發(fā)出了取消請(qǐng)求,RunWorkerCompleted事件處理程序中RunWorkerCompletedEventArgs的 Cancelled 標(biāo)志也不會(huì)設(shè)置為 true。這種情況被稱(chēng)作爭(zhēng)用狀態(tài)。(可以通過(guò)直接監(jiān)控組件的CancellationPending屬性,來(lái)做判斷)
5) 確保在DoWork事件處理程序中不操作任何用戶(hù)界面對(duì)象。而應(yīng)該通過(guò)ProgressChanged和RunWorkerCompleted事件與用戶(hù)界面進(jìn)行通信。
因?yàn)镽unWorkerAsync() 是通過(guò)委托的BeginInvoke() 引發(fā)的DoWork事件,即DoWork事件的執(zhí)行線程已不是創(chuàng)建控件的線程(我在《異步編程:異步編程模型 (APM)》中介紹了幾種夸線程訪問(wèn)控件的方式)。而ProgressChanged和RunWorkerCompleted事件是通過(guò)幫助器類(lèi)AsyncOperation的 Post() 方法使其調(diào)用發(fā)生在合適的“線程或上下文”中。
#p#
自定義基于事件的異步組件
剛才我們介紹了BackgroundWorker組件,但是這個(gè)組件在一個(gè)時(shí)刻只能開(kāi)啟一個(gè)異步操作,那如果我們要想同時(shí)支持多個(gè)異步操作、進(jìn)度報(bào)告、增量結(jié)果、取消和返回結(jié)果值或異常信息該怎么辦呢?對(duì)的,我們可以為自己定義一個(gè)基于事件的異步組件。
我直接引用MSDN上的一則計(jì)算質(zhì)數(shù)的異步組件示例,請(qǐng)從我提供的示例代碼中獲取。
質(zhì)數(shù)算法:埃拉托色尼篩法
eg:判斷n是否為質(zhì)數(shù) 1、1和0既非素?cái)?shù)也非合數(shù); 2、將2和3加入質(zhì)數(shù)集合primes;從n=5開(kāi)始,通過(guò) n+=2 來(lái)跳過(guò)所有偶數(shù); 3、循環(huán)集合primes中的質(zhì)數(shù)并將其做為n的因子,能整除的為合數(shù); 4、若不能整除,則繼續(xù)循步驟3直到“因子的平方>n”,即可判斷n為質(zhì)數(shù),并將其加入到集合primes。 |
來(lái)個(gè)示例截圖吧:
示例分析:(組件名:PrimeNumberCalculator)
1. 首先我們?yōu)镻rimeNumberCalculator組件注冊(cè)ProgressChanged(進(jìn)度報(bào)告) 和CalculatePrimeCompleted(完成通知)事件;
2. 使用CalculatePrimeAsync(intnumberToTest, object taskId)開(kāi)啟異步任務(wù),注意我們需要傳遞一個(gè)唯一標(biāo)識(shí)Guid taskId = Guid.NewGuid();用于標(biāo)識(shí)取消的操作,并傳遞給CompletedEventArgs和ProgressChangedEventArgs參數(shù)的UserState屬性來(lái)標(biāo)識(shí)當(dāng)前引發(fā)進(jìn)度或完成事件的特定異步任務(wù);
3. 取消操作CancelAsync(object taskId),只是將taskId對(duì)應(yīng)的AsyncOperation實(shí)例移除內(nèi)部任務(wù)集合,耗時(shí)操作通過(guò)判斷taskId是否存在于集合來(lái)判斷其是否被取消;
此文到此結(jié)束,通過(guò)此博文我們認(rèn)識(shí)到:
1) 基于事件的異步編程是通過(guò)AsyncOperationManager類(lèi)和AsyncOperation類(lèi)兩個(gè)幫助器類(lèi)確保你的異步操作支持在各種應(yīng)用程序模型(包括 ASP.NET、控制臺(tái)應(yīng)用程序和 Windows 窗體應(yīng)用程序)的適當(dāng)“線程或上下文”調(diào)用訪問(wèn)控件;
2) BackgroundWorker組件構(gòu)建、使用和缺點(diǎn)。
3) 展現(xiàn)如何構(gòu)建一個(gè)基于事件的異步組件,并且支持多個(gè)異步操作的并行運(yùn)行
感謝大家的觀賞,如本文對(duì)你有幫助還請(qǐng)多幫推薦支持下……
原文鏈接:http://www.cnblogs.com/heyuquan/archive/2013/04/01/2993085.html