目錄算法
27.1 CLR線程池基礎安全
27.2 執行簡單的計算限制操做數據結構
27.3 執行上下文併發
27.4 協做式取消和超時異步
27.5 任務性能
27.6 Parallel的靜態For,ForEach和Invoke方法spa
27.7 並行語言集成查詢(PLINQ)線程
27.8 執行定時計算限制操做調試
27.9 線程池如何管理線程orm
異步執行計算限制操做,容許線程池在多個CPU內核上調度任務,使多個線程能併發工做,從而高效率地使用系統資源,同時提高應用程序的吞吐能力。
線程池是你的應用程序能使用的線程集合。每CLR一個線程池:這個線程池由CLR控制的全部AppDomain共享。
CLR初始化時,線程池中是沒有線程的。在內部,線程池維護了一個操做請求隊列。應用程序執行一個異步操做時,就調用某個方法,將一個記錄項追加到線程池隊列中。線程池的代碼從這個隊列中提取記錄項,將這個記錄項派發給一個線程池線程。
將一個異步的計算限制操做放到線程池隊列中:ThreadPool類
static Boolean QueueUserWorkItem(WaitCallback callback);
static Boolean QueueUserWorkItem(WaitCallback callback, Object state);
每一個線程都關聯了一個執行上下文數據結構。執行上下文包括的東西有安全設置(壓縮棧,Thread的Principal屬性和Winodws身份)、宿主設置以及邏輯調用上下文數據。
ExecutionContext類:
[SecurityCritical] public static AsyncFlowControl SuppressFlow();
public static void RestoreFlow();
public static Boolean IsFlowSuppressed();
Microsoft .NET Framework 提供了標準的取消操做模式。這個模式是協做式的,意味着要取消的操做必須顯示支持取消。
System.Threading.CancellationTokenSoure包含了和管理取消有光的全部狀態。
public struct CancellationToken:
CancellationToken 實例是輕量級值類型,包含單個私有字段,即對其CancellationToken的IsCancellationRequested屬性,瞭解循環是否應該提早終止,從而終止計算限制的操做。
System.Threading.Tasks命名空間
27.5.1 等待任務完成並獲取結果
若是計算限制的任務拋出未處理的異常,異常會被「吞噬」並存儲到一個集合中,而線程池線程能夠返回到線程池中。調用Wait方法或者Result屬性時,這些成員會拋出一個System.AggregateException對象
27.5.2 取消任務
可調用一個CancellationTokenSource取消Task。
27.5.3 任務完成時自動啓動新任務
伸縮性好的軟件不該該使線程阻塞
27.5.4 任務能夠啓動子任務
任務支持父/子關係。
27.5.5 任務內部揭祕
每一個Task對象都有一組字段,這些字段構成了任務的狀態。其中包括一個Int32ID,表明Task執行狀態的一個Int32,對父任務的引用,對Task建立時指定的TaskScheduler的引用,對回調方法的引用,對要傳給回調方法的對象的引用,對ExecutionContext的引用以及對MenualResetEventSlim對象的引用。另外,每一個Task對象都有對根據須要建立的補充狀態的引用。補充狀態包含了一個CancellationToken,一個ContinueWithTask對象集合,爲拋出未處理異常的子任務而準備的一個Task對象集合等。
首次構造Task對象時,它的狀態時Created。之後,當任務啓動時,它的狀態變成WaitingToRun。Task實際在一個線程上運行時,它的狀態變成Runing。任務中止運行,並等待它的任何子任務時,狀態變成WaitingForChildrenToComplete。任務完成時進入如下狀態之一:RanToCompletion(運行完成),Canceld(取消)或Faulted(出錯)。
27.5.6 任務工廠
TaskFactory
27.5.7 任務調度器
TaskScheduler對象負責執行被調度的任務,同時向Visual Studio調試器公開任務信息。FCL提供了兩個派生自TaskScheduler的類型:線程池任務調度器,和同步上下文任務調度器。任務調度器將任務調度給線程池的工做者線程。
System.Threading.Tasks.Parallel:For,ForEach,Invoke
Parallel的全部方法都讓調用線程參與處理。調用Parallel方法的前提是:工做項必須能並行執行。另外,要避免會修改任何共享數據的工做項,不然多個線程同時處理可能會損壞數據。
重載版本:
接受ParallelOptions對象:
CancellationToke:容許取消操做。
Int32MaxDegreeOfParallelism:容許指定能夠併發操做的最大工做項目數。
TaskSchedulerTaskScheduler:容許指定要使用哪一個TaskScheduler。
任務局部初始化委託:爲參與工做的每一個任務都調用一次該委託。這個委託是在任務別要求處理一個工做項以前調用的。
主體委託:爲參與工做的各個線程所處理的每一項都調用一次該委託。
任務局部終結委託:爲參與工做的每個任務都調用一次該委託。這個委託是在任務處理好派發給它的全部工做項以後調用。即便主體委託代碼引起一個未處理的異常,也會調用它。
使用LINQ to Objects時,只有一個線程順序處理數據集合中的全部項:咱們稱之爲順序查詢。要提升處理性能,可使用並行LINQ(parallel LINQ),它將順序查詢轉換成並行查詢,在內部使用任務,將集合中的數據項的處理工做分散到多個CPU上,以便併發處理多個數據項。
AsParallel;AsSequential
System.Threading命名空間定義了一個Timer類,可用它讓一個線程池線程定時調用一個方法。
System.Threading的Timer類:要在一個線程池線程上執行定時的(週期性發生的)後臺任務,它是最好的計時器。
System.Windows.Forms的Timer類:構造這個類的實例,至關於告訴Windows將一個計時器和調用線程關聯。
System.Windows.Threading的DispatcherTimer類:這個類是System.Windows.Forms的Timer類在Silverlight和WPF應用程序中的等價物。
Windows.UI.Xaml的DispatcherTimer類:這個類是System.Windows.Forms的Timer類在Windows Store應用中的等價物。
System.Timers的Timer類:這個計時器本質上是System.Threading的Timer類包裝器。計時器到期(觸發)會致使CLR將事件放到線程池隊列中。(不建議使用)
27.9.1 設置線程池限制
CLR容許開發人員設置線程池要建立的最大線程數。但實踐證實,線程池永遠都不該該設置線程數上限,由於可能發生飢餓或死鎖。
27.9.2 如何管理工做者線程
ThreadPool.QueueUserWorkItem方法和TImer類老是將工做項放到全局隊列中。工做者線程採用一個先入先出(FIFO)算法將工做項從這個隊列中取出,並處理它們。因爲多個工做者線程可能同時從全局隊列中拿走工做項,因此全部工做者線程都競爭一個線程同步鎖,以保證兩個或多個線程不會獲取同一個工做項。
每一個工做者線程都有本身的本地隊列。工做者線程調度一個Task時,該Task被添加到調用線程的本地隊列。非工做者線程調度一個Task時,該Task被添加到全局隊列。工做者線程採用後入先出(LIFO)算法將任務從本地隊列中取出。因爲工做者線程是惟一容許訪問它本身的本地隊列頭的線程,因此無需同步鎖,並且在隊列中添加和刪除Task的速度很是快,