作業系統使用進程將它們正在執行的不同應用程式分開。線程是作業系統分配處理器時間的基本單元,並且進程中可以有多個線程同時執行代碼。每個線程都維護例外處理常式、調度優先順序和一組系統用於在調度該線程前儲存線程內容相關的結構。線程上下文包括為使線程線上程的宿主進程地址空間中無縫地繼續執行所需的所有資訊,包括線程的 CPU 寄存器組和堆棧。
.NET Framework 將作業系統進程進一步細分為由 System::AppDomain 表示的、稱為應用程式定義域的輕量託管子進程。一個或多個託管線程(由 System.Threading::Thread 表示)可以在同一個主控處理序中的一個或任意數目的應用程式定義域中運行。雖然每個應用程式定義域都是用單個線程啟動的,但該應用程式定義域中的代碼可以建立附加應用程式定義域和附加線程。其結果是託管線程可以在同一個非主控處理序中的應用程式定義域之間自由移動;您可能只有一個線程在若干應用程式定義域之間移動。
支援搶先多任務處理的作業系統可以建立多個進程中的多個線程同時執行的效果。它通過以下方式實現這一點:在需要處理器時間的線程之間分割可用處理器時間,並輪流為每個線程分配處理器時間片。當前執行的線程在其時間片結束時被掛起,而另一個線程繼續運行。當系統從一個線程切換到另一個線程時,它將儲存被搶先的線程的線程上下文,並重新載入線程隊列中下一個線程的已儲存線程上下文。
時間片的長度取決於作業系統和處理器。由於每個時間片都很小,因此即使只有一個處理器,多個線程看起來似乎也是在同時執行。這實際上就是多處理器系統中發生的情形,在此類系統中,可執行線程分布在多個可用處理器中。
何時使用多個線程
需要使用者互動的軟體必須儘可能快地對使用者的活動作出反應,以便提供豐富多彩的使用者體驗。但同時它必須執行必要的計算以便儘可能快地將資料呈現給使用者。如果應用程式僅使用一個執行線程,則可以將非同步編程與 .NET Framework 遠端或使用 ASP.NET 建立的 XML Web services 結合使用,在使用自己的電腦的處理時間之外還使用其他電腦的處理時間,從而提高對使用者的響應速度並減少應用程式的資料處理時間。如果您進行中大量的輸入/輸出工作,則還可以使用 I/O 完成連接埠來提高應用程式的響應速度。
多個線程的優點
無論如何,要提高對使用者的響應速度並且處理所需資料以便幾乎同時完成工作,使用多個線程是一種最為強大的技術。在具有一個處理器的電腦上,多個線程可以通過利用使用者事件之間很小的時間段在幕後處理資料來達到這種效果。例如,在另一個線程正在重新計算同一應用程式中的試算表的其他部分時,使用者可以編輯該試算表。
無需修改,同一個應用程式在具有多個處理器的電腦上運行時將極大地滿足使用者的需要。單個應用程式定義域可以使用多個線程來完成以下任務:
多個線程的缺點
建議您使用儘可能少的線程,這樣可以最大限度地減少作業系統資源的使用,並可提高效能。線程處理還具有在設計應用程式時要考慮的資源要求和潛在衝突。這些資源要求如下所述:
系統將為進程、AppDomain 對象和線程所需的上下文資訊使用記憶體。因此,可以建立的進程、AppDomain 對象和線程的數目會受到可用記憶體的限制。
跟蹤大量的線程將佔用大量的處理器時間。如果線程過多,則其中大多數線程都不會產生明顯的進度。如果大多數當前線程處於一個進程中,則其他進程中的線程的調度頻率就會很低。
使用許多線程式控制制代碼執行非常複雜,並可能產生許多 bug。
銷毀線程需要瞭解可能發生的問題並對那些問題進行處理。
提供對資源的共用訪問會造成衝突。為了避免衝突,必須對共用資源進行同步或控制對共用資源的訪問。如果在相同或不同的應用程式定義域中未能正確地使訪問同步,則會導致出現一些問題,這些問題包括死結和競爭條件等,其中死結是指兩個線程都停止回應,並且都在等待對方完成;競爭條件是指由於意外地出現對兩個事件的執行時間的臨界依賴性而發生反常的結果。系統提供了可用於協調多個線程之間的資源共用的同步對象。減少線程的數目使同步資源更為容易。
需要同步的資源套件括:
線程處理與應用程式設計
一般情況下,要為不會阻止其他線程的相對較短的任務處理多個線程並且不需要對這些任務執行任何特定調度時,使用 ThreadPool 類是一種最簡單的方式。但是,有多個理由建立您自己的線程:
如果您需要使一個任務具有特定的優先順序。
如果您具有可能會長時間運行(並因此阻止其他任務)的任務。
如果您需要將線程放置到單一執行緒 Apartment中(所有 ThreadPool 線程均處於多執行緒 Apartment中)。
如果您需要與該線程關聯的穩定標識。例如,您應使用一個專用線程來中止該線程,將其掛起或按名稱發現它。
如果您需要運行與使用者介面互動的後台線程,.NET Framework 2.0 版提供了 BackgroundWorker 組件,該組件可以使用事件與使用介面執行緒的跨線程封送進行通訊。
線程處理和異常
線上程中執行異常處理。線程(甚至是後台線程)中的未處理的例外狀況通常會終止進程。以下為此規則的三種例外情況:
有關更多資訊,請參見託管線程中的異常。