多執行緒應用程式 (C# 和 Visual Basic)
使用 Visual Basic 和 C#,您就可以撰寫能夠同時執行多個工作的應用程式。 可能妨礙其他工作的工作可以在個別執行緒上執行,這也就是名為「多執行緒」(Multithreading) 或「無限制執行緒」(Free Threading) 的處理序。
使用多執行緒的應用程式較能回應使用者輸入,因為當佔用大量處理器資源的工作在個別執行緒上執行時,使用者介面還是保持作用中的狀態。 當您建立可擴充的應用程式時,多執行緒也相當有用,因為您可以隨著工作量的增加來加入執行緒。
注意事項 |
---|
Visual Studio 2010 和 .NET Framework 4 提供了新的執行階段、新的類別庫型別和新的診斷工具,以加強支援平行程式設計。 如需詳細資訊,請參閱 以 .NET Framework 進行平行程式設計。 |
使用 BackgroundWorker 元件
建立多執行緒應用程式的最可靠方式是使用 BackgroundWorker 元件。 這個類別會管理專門用於處理您所指定之方法的不同執行緒。 如需範例,請參閱 逐步解說:使用 BackgroundWorker 元件進行多執行緒處理 (C# 和 Visual Basic)。
若要在背景開始作業,請建立 BackgroundWorker,並接聽用於報告作業進度,以及在作業完成時發出信號的事件。 您可以用程式設計方式建立 BackgroundWorker 物件,或將它從 [工具箱] 的 [元件] 索引標籤中拖曳到表單。 如果在 [表單設計工具] 中建立 BackgroundWorker,則此元件會出現在 [元件匣] 中,且它的屬性會顯示在 [屬性] 視窗中。
設定背景作業
若要設定背景作業,請加入 DoWork 事件的事件處理常式。 在這個事件處理常式中呼叫耗時作業。
若要啟動作業,請呼叫 RunWorkerAsync。 若要接收進度更新的告知,請處理 ProgressChanged 事件。 若要在作業完成時接收告知,請處理 RunWorkerCompleted 事件。
因為是在呼叫 RunWorkerAsync 方法的執行緒上引發 ProgressChanged 和 RunWorkerCompleted 事件,所以處理那些事件的方法可以存取應用程式的使用者介面。 然而,因為 DoWork 事件處理常式是在背景執行緒中執行,所以它無法與任何使用者介面物件搭配使用。
建立和使用執行緒
如果需要更加控制應用程式執行緒的行為,您可以自己管理這些執行緒。 但是請注意,撰寫正確的多執行緒應用程式十分困難:應用程式可能會停止回應或因競爭情況而發生暫時性 (Transient) 錯誤。 如需詳細資訊,請參閱 安全執行緒的元件。
透過宣告 Thread 型別的變數,並呼叫建構函式,提供您要在新執行緒上執行之程序或方法的名稱,即可建立新的執行緒。 下列程式碼提供一個範例。
Dim newThread As New System.Threading.Thread(AddressOf AMethod)
System.Threading.Thread newThread =
new System.Threading.Thread(AMethod);
啟動和停止執行緒
若要啟動新執行緒的執行,請使用 Start 方法,如下列程式碼所示。
newThread.Start()
newThread.Start();
若要停止執行緒的執行,請使用 Abort 方法,如下列程式碼所示。
newThread.Abort()
newThread.Abort();
除了啟動和停止執行緒之外,也可以呼叫 Sleep 或 Suspend 方法以暫停執行緒、使用 Resume 方法以繼續暫停的執行緒,以及使用 Abort 方法以終結執行緒。
執行緒方法
下表列出一些您可用來控制個別執行緒的方法。
方法 |
動作 |
---|---|
讓執行緒開始執行。 |
|
暫停執行緒一段指定的時間。 |
|
當執行緒到達安全點時暫停執行緒。 |
|
當執行緒到達安全點時停止執行緒。 |
|
重新啟動暫停的執行緒。 |
|
讓目前的執行緒等待另一個執行緒完成。 如果與逾時值搭配使用,而執行緒在指定時間內完成,則這個方法會傳回 True。 |
安全點
這些方法大部分是自我闡明,但「安全點」(Safe Point) 對您而言可能是新的概念。 對 Common Language Runtime 而言,安全點是在程式碼中能安全執行自動「記憶體回收」(Garbage Collection) 的位置,記憶體回收是一個釋放未使用的變數並重新利用記憶體的處理序。 呼叫執行緒的 Abort 或 Suspend 方法時,Common Language Runtime 會分析程式碼並判斷停止執行執行緒的適當位置。
執行緒屬性
執行緒也包含數個有用的屬性,如下表所示:
屬性 |
值 |
---|---|
如果執行緒在作用中,則包含值 True。 |
|
取得或設定指示執行緒是否是或應該是背景執行緒的布林值。 背景執行緒就像前景執行緒一樣,但背景執行緒不能避免處理序停止。 一旦停止所有屬於處理序的前景執行緒,Common Language Runtime 會針對執行中之背景執行緒呼叫 Abort 方法以結束處理序。 |
|
取得或設定執行緒的名稱。 最常用於在偵錯時探索個別執行緒。 |
|
取得或設定作業系統用來設定執行緒排程之優先權的值。 |
|
取得或設定特定執行緒所使用的執行緒模型。 執行緒模型在執行緒呼叫 Unmanaged 程式碼時很重要。 |
|
包含描述執行緒狀態的值。 |
執行緒優先權
每個執行緒都具有優先權屬性,用於判斷它有多少處理器時間執行。 作業系統會配置較長的時間給高優先權執行緒,而配置較短的時間給低優先權執行緒。 新執行緒是使用值 Normal 建立的,但是您可以將 Priority 屬性變更為 ThreadPriority 列舉中的任何值。
如需各種執行緒優先權的詳細描述,請參閱 ThreadPriority。
前景和背景執行緒
「前景執行緒」(Foreground Thread) 永遠是處於執行的狀態,而「背景執行緒」(Background Thread) 則會在最後一個前景執行緒停止時結束。 您可以使用 IsBackground 屬性,判斷或變更執行緒的背景狀態。
在表單和控制項使用多執行緒
儘管多執行緒最適用於執行程序與類別方法 (Class Method),但您也可以將它使用在表單及控制項。 如果您要這麼做,請注意下列幾點:
盡量只在用來建立控制項的執行緒上執行控制項的方法。 如果您必須從另一個執行緒呼叫控制項的方法,則必須使用 Invoke 呼叫方法。
請不要使用 SyncLock (Visual Basic) 或 lock (C#) 陳述式,來鎖定操作控制項或表單的執行緒。 由於控制項和表單的方法有時會回呼至呼叫程序,因此最後可能會不慎產生死結 (Deadlock),在這個情況下,兩執行緒會等候彼此釋放鎖定,而使得應用程式中止。
請參閱
參考
概念
多執行緒程序的參數和傳回值 (C# 和 Visual Basic)