在.NET多線程程序中使用異步調用的簡易方法
原創【51CTO獨家特稿】簡介
對于開發者來說,運行異步任務簡直就是一場惡夢,特別是初學者更是如此。在本文附帶的代碼中,您將發現一個簡單的AsyncWorker類,它能夠使您輕松完成異步任務的處理,即使您對異步調用沒有全面深入的了解。當然,我們也很希望看到您貢獻的代碼,尤其是對于ReportProgress函數,因為它還未經測試。
背景知識
我為什么編寫這個助手類(helper class)呢? 簡單地說,這是因為我不喜歡.NET BackgroundWorker類,以及所有與IsBusy參數有關的問題。有時候,即使您成功地終止了異步任務,IsBusy也不會從true變為false。類backgroundWorker會強迫您在while循環中使用Application.DoEvents。也許還有其它正確使用它的方法,但是我至今還沒找到。我嘗試按照backgroundWorker的設計方法建立一個盡可能簡單的替換物。
代碼用法
如果您看過BackgroundWorker的文檔,那么使用下面的代碼也應該不成問題。為了初始化AsyncWorker,我們做如下定義:
AsyncCallback m_asyncWorker;
然后,在您的代碼(構造函數)中對其進行初始化,如下所示:
- //通過設置maximumCount,我們可以對簡單的ThreadPool進行摹擬。
- //參數maximumCount用于指出可以同時啟動多少個并行的線程。如果abortIfBusyParameter被設為true,那么其他線程就只能等待,或者被拒絕。
- this.m_asyncWorker = new AsyncWorker(1);
- //分配一個后臺任務
- this.m_asyncWorker.DoWork += new DoWorkEventHandler(m_asyncWorker_DoWork);
您的后臺任務可以是任何您喜歡的東西:
- void m_asyncWorker_DoWork(object sender, DoWorkEventArgs e) {
- Console.WriteLine("Hello world! I was started asynchronously.");
- }
最后調用background worker :
- //因為abortIfBusyParameter 被設置為true,所以如果前面的調用仍然在運行的話,RunWorkerAsync將返回false(中止調用)。
- if (!this.m_asyncWorker.RunWorkerAsync(true)) {
- Console.WriteLine("Worker in use....");
- }
通過把RunWorkerAsync參數abortIfBusy設置為true,即使前面的異步調用仍在運行,您也可以跳過這個事件。通過將其設為false,它會進入一個等待隊列,并在IsBusy從true轉換為false的時候馬上觸發。 這個機制對于性能敏感的應用程序來說非常有用。如果您有許多啟動異步調用的“低優先級”事件,并且如果前面的異步調用仍在運行(IsBusy),那么您可以決定是否應該啟動另一個異步調用。
例如:如果您在屏幕上拖動一個對象的時候,那么就無需每次都重繪它。只有當IsBusy為false的時候才需對其進行繪制。 如果您想要獲得平滑效果,只需增加maximumCount(您的線程池)即可。
最后,如果您需要一個回調函數,那么您可以自己預訂RunWorkerCompleted事件。
- //分配RunWorkerCompleted。它是您的回調函數事件。
- this.m_asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_asyncWorker_RunWorkerCompleted);
結束語
希望這個工具可以使您的生活變得更加輕松。請不要詢問JustDoSomething類的鎖定問題,因為它是其它測試的一部分。
【編輯推薦】