基於事件的非同步模式概述

2022-01-23 01:36:21 字數 3467 閱讀 8602

msdn

那些同時執行多項任務、但仍能響應使用者互動的應用程式通常需要實施一種使用多執行緒的設計方案。system.threading 命名空間提供了建立高效能多執行緒應用程式所必需的所有工具,但要想有效地使用這些工具,需要有豐富的使用多執行緒軟體工程的經驗。對於相對簡單的多執行緒應用程式,backgroundworker 元件提供了乙個簡單的解決方案。對於更複雜的非同步應用程式,請考慮實現乙個符合基於事件的非同步模式的類。

基於事件的非同步模式具有多執行緒應用程式的優點,同時隱匿了多執行緒設計中固有的許多複雜問題。使用支援此模式的類,您將能夠:

同時執行多個操作,每個操作完成時都會接到通知。

等待資源變得可用,但不會停止(「掛起」)您的應用程式。

使用熟悉的事件和委託模型與掛起的非同步操作通訊。有關使用事件處理程式和委託的更多資訊,請參見事件和委託。

支援基於事件的非同步模式的類將有乙個或多個名為 methodnameasync的方法。這些方法可能會建立同步版本的映象,這些同步版本會在當前執行緒上執行相同的操作。此類還可能有乙個methodnamecompleted事件,而且它可能會有乙個 methodnameasynccancel(或只是cancelasync)方法。

警告基於事件的非同步模式可以採用多種形式,具體取決於某個特定類支援的操作的複雜程度。最簡單的類可能只有乙個 methodnameasync方法和乙個對應的 methodnamecompleted事件。更複雜的類可能有若干個 methodnameasync方法(每種方法都有乙個對應的 methodnamecompleted事件),以及這些方法的同步版本。這些類分別支援各種非同步方法的取消、進度報告和增量結果。

非同步方法可能還支援多個掛起的呼叫(多個並行呼叫),允許您的**在此方法完成其他掛起的操作之前呼叫此方法任意多次。若要正確處理此種情況,必須讓您的應用程式能夠跟蹤各個操作的完成。

soundplayer

picturebox元件表示基於事件的非同步模式的簡單實現。webclient

backgroundworker元件表示基於事件的非同步模式的更複雜的實現。

下面是乙個符合此模式的類宣告示例:

public

class

asyncexample

//class implementation not shown.

}

這裡虛構的 asyncexample 類有兩個方法,都支援同步和非同步呼叫。同步過載的行為類似於方法呼叫,它們對呼叫執行緒執行操作;如果操作很耗時,則呼叫的返回可能會有明顯的延遲。非同步過載將在另乙個執行緒上啟動操作,然後立即返回,允許在呼叫執行緒繼續執行的同時讓操作「在後台」執行。

非同步操作可以有兩個過載:單調用和多呼叫。您可以通過方法簽名來區分這兩種形式:多呼叫形式有乙個額外的引數,即 userstate。使用這種形式,您的**可以多次呼叫 method1async(string param, object userstate),而不必等待任何掛起的非同步操作的完成。另一方面,如果您嘗試在前乙個呼叫尚未完成時呼叫 method1async(string param),該方法將引發invalidoperationexception。

多呼叫過載的 userstate 引數可幫助您區分各個非同步操作。您應分別為各個 method1async(string param, object userstate) 呼叫提供乙個唯一值(例如 guid 或雜湊**);這樣,當各個操作完成時,您的事件處理程式便可以確定哪個操作的例項引發了完成事件。

如果您使用多呼叫過載,您的**將需要跟蹤掛起的任務的 userstate 物件(任務 id)。對於每個 method1async(string param, object userstate) 呼叫,您通常應生成乙個新的、唯一的userstate 物件並將此物件新增到集合中。當對應於此 userstate 物件的任務引發完成事件時,您的完成方法實現將檢查 system.componentmodel.asynccompletedeventargs.userstate 並將此物件從集合中刪除。在以這種方式使用時,userstate 引數充當任務 id 的角色。

注意在為您對多呼叫過載的呼叫中的 userstate 提供唯一值時,一定要小心。如果任務 id 不唯一,將導致非同步類引發 argumentexception。

我們必須能夠在非同步操作完成之前隨時取消它們,這一點很重要。實現基於事件的非同步模式的類將有乙個cancelasync方法(如果有多個非同步方法)或 methodnameasynccancel方法(如果只有乙個非同步方法)。

允許多個呼叫的方法採用 userstate 引數,此引數可用來跟蹤各個任務的生存期。cancelasync採用 userstate 引數,此引數允許您取消特定的掛起任務。

一次只支援乙個掛起的操作的方法(如 method1async(string param))是不可取消的。

符合基於事件的非同步模式的類可以為跟蹤進度和增量結果提供事件。此事件通常叫做progresschanged或 methodnameprogresschanged,它對應的事件處理程式會帶有乙個progresschangedeventargs 引數。

progresschanged事件的事件處理程式可以檢查 system.componentmodel.progresschangedeventargs.progresspercentage 屬性來確定非同步任務完成的百分比。此屬性的範圍是 0 到 100,可用來更新 progressbar 的 value 屬性。如果有多個非同步操作掛起,您可以使用 system.componentmodel.progresschangedeventargs.userstate 屬性來分辨出哪個操作在報告進度。

一些類可能會在非同步操作繼續時報告增量結果。這些結果將儲存的派生自progresschangedeventargs的類中,並顯示為此派生類中的屬性。您可以在progresschanged事件的事件處理程式中訪問這些結果,就像訪問progresspercentage屬性一樣。如果有多個非同步操作掛起,您可以使用userstate屬性來分辨出哪個操作在報告增量結果。

任務如何:使用支援基於事件的非同步模式的元件

如何:在後台執行操作

如何:實現使用後台操作的窗體

參考progresschangedeventargs

backgroundworker

asynccompletedeventargs

概念實現基於事件的非同步模式的最佳做法

確定何時實現基於事件的非同步模式

其他資源

使用基於事件的非同步模式進行多執行緒程式設計

基於事件的非同步模式。

由於乙個類可以不用顯示的啟動或者管理執行緒而有多執行緒的能力,因此通過這就提供了乙個簡單的手段來實現,基於事件的非同步模式 event based asynchronous pattern eap 它同時也具有以下特徵 可協調的退出模式。當工作執行緒完成時,可以安全的更新wpf或者windowfor...

基於事件的非同步程式設計模式

public class backgroundworker component 通常的使用方法如下 在dowork中新增乙個事件處理程式,在該事件處理程式中呼叫耗時的操作 呼叫 runworkerasync啟動才操作。如果想要得到當前的更新進度,在progresschanged事件處理程式中處理,如...

基於事件的非同步程式設計模式

public class backgroundworker component 通常的使用方法如下 在dowork中新增乙個事件處理程式,在該事件處理程式中呼叫耗時的操作 呼叫 runworkerasync啟動才操作。如果想要得到當前的更新進度,在progresschanged事件處理程式中處理,如...