1. 程式人生 > >.NET並行處理和並發1-Threads and Theading

.NET並行處理和並發1-Threads and Theading

地址空間 mode http exception 上下文 依賴 asp.net 代碼執行 線程隊列

線程是操作系統分配處理器時間的基本單元,並且進程中可以有多個線程同時執行代碼。 每個線程都維護異常處理程序、調度優先級和一組系統用於在調度該線程前保存線程上下文的結構。 線程上下文包括為使線程在線程的宿主進程地址空間中無縫地繼續執行所需的所有信息,包括線程的 CPU 寄存器組和堆棧。

.NET Framework 將操作系統進程進一步細分為由 System.AppDomain 表示的、稱為應用程序域的輕量托管子進程。 一個或多個托管線程(由System.Threading.Thread 表示)可以在同一個托管進程中的一個或任意數目的應用程序域中運行。 雖然每個應用程序域都是用單個線程啟動的,但該應用程序域中的代碼可以創建附加應用程序域和附加線程。 其結果是托管線程可以在同一個非托管進程中的應用程序域之間自由移動;您可能只有一個線程在若幹應用程序域之間移動。

支持搶先多任務處理的操作系統可以創建多個進程中的多個線程同時執行的效果。 它通過以下方式實現這一點:在需要處理器時間的線程之間分割可用處理器時間,並輪流為每個線程分配處理器時間片。 當前執行的線程在其時間片結束時被掛起,而另一個線程繼續運行。 當系統從一個線程切換到另一個線程時,它將保存被搶先的線程的線程上下文,並重新加載線程隊列中下一個線程的已保存線程上下文。

時間片的長度取決於操作系統和處理器。 由於每個時間片都很小,因此即使只有一個處理器,多個線程看起來似乎也是在同時執行。 這實際上就是多處理器系統中發生的情形,在此類系統中,可執行線程分布在多個可用處理器中。

何時使用多個線程

需要用戶交互的軟件必須盡可能快地對用戶的活動作出反應,以便提供豐富多彩的用戶體驗。 但同時它必須執行必要的計算以便盡可能快地將數據呈現給用戶。 如果應用程序僅使用一個執行線程,則可以將異步編程與 .NET Framework 遠程處理或使用 ASP.NET 創建的 XML Web services 結合使用,在使用自己的計算機的處理時間之外還使用其他計算機的處理時間,從而提高對用戶的響應速度並減少應用程序的數據處理時間。 如果您正在進行大量的輸入/輸出工作,則還可以使用 I/O 完成端口來提高應用程序的響應速度。

多個線程的優點

無論如何,要提高對用戶的響應速度並且處理所需數據以便幾乎同時完成工作,使用多個線程是一種最為強大的技術。 在具有一個處理器的計算機上,多個線程可以通過利用用戶事件之間很小的時間段在後臺處理數據來達到這種效果。 例如,在另一個線程正在重新計算同一應用程序中的電子表格的其他部分時,用戶可以編輯該電子表格。

無需修改,同一個應用程序在具有多個處理器的計算機上運行時將極大地滿足用戶的需要。 單個應用程序域可以使用多個線程來完成以下任務:

  • 通過網絡與 Web 服務器和數據庫進行通信。

  • 執行占用大量時間的操作。

  • 區分具有不同優先級的任務。 例如,高優先級線程管理時間關鍵的任務,低優先級線程執行其他任務。

  • 使用戶界面可以在將時間分配給後臺任務時仍能快速做出響應

多個線程的缺點

建議您使用盡可能少的線程,這樣可以最大限度地減少操作系統資源的使用,並可提高性能。 線程處理還具有在設計應用程序時要考慮的資源要求和潛在沖突。 這些資源要求如下所述:

  • 系統將為進程、AppDomain 對象和線程所需的上下文信息使用內存。 因此,可以創建的進程、AppDomain 對象和線程的數目會受到可用內存的限制。

  • 跟蹤大量的線程將占用大量的處理器時間。 如果線程過多,則其中大多數線程都不會產生明顯的進度。 如果大多數當前線程處於一個進程中,則其他進程中的線程的調度頻率就會很低。

  • 使用許多線程控制代碼執行非常復雜,並可能產生許多 bug。

  • 銷毀線程需要了解可能發生的問題並對那些問題進行處理。

提供對資源的共享訪問會造成沖突。 為了避免沖突,必須對共享資源進行同步或控制對共享資源的訪問。 如果在相同或不同的應用程序域中未能正確地使訪問同步,則會導致出現一些問題,這些問題包括死鎖和爭用條件等,其中死鎖是指兩個線程都停止響應,並且都在等待對方完成;爭用條件是指由於意外地出現對兩個事件的執行時間的臨界依賴性而發生反常的結果。 系統提供了可用於協調多個線程之間的資源共享的同步對象。 減少線程的數目使同步資源更為容易。

需要同步的資源包括:

  • 系統資源(如通信端口)。

  • 多個進程所共享的資源(如文件句柄)。

  • 由多個線程訪問的單個應用程序域的資源(如全局、靜態和實例字段)。

線程處理與應用程序設計

一般情況下,要為不會阻止其他線程的相對較短的任務處理多個線程並且不需要對這些任務執行任何特定調度時,使用 ThreadPool 類是一種最簡單的方式。 但是,有多個理由創建您自己的線程:

  • 如果您需要使一個任務具有特定的優先級。

  • 如果您具有可能會長時間運行(並因此阻止其他任務)的任務。

  • 如果您需要將線程放置到單線程單元中(所有 ThreadPool 線程均處於多線程單元中)。

  • 如果您需要與該線程關聯的穩定標識。 例如,您應使用一個專用線程來中止該線程,將其掛起或按名稱發現它。

  • 如果您需要運行與用戶界面交互的後臺線程,.NET Framework 2.0 版提供了 BackgroundWorker 組件,該組件可以使用事件與用戶界面線程的跨線程封送進行通信。

線程處理和異常

在線程中執行異常處理。 線程(甚至是後臺線程)中的未經處理的異常通常會終止進程。 以下為此規則的三種例外情況:

  • 由於調用了 Abort,線程中將引發 ThreadAbortException。

  • 由於正在卸載應用程序域,線程中將引發 AppDomainUnloadedException。

  • 公共語言運行時或宿主進程將終止線程。

.NET並行處理和並發1-Threads and Theading