異步的限制操做主要做用於其餘執行線程,例如規則檢查、音頻或視頻數據轉碼以及生成圖形略縮圖,在金融和建築工程應用程序中,計算限制的操做也是十分廣泛的。編程
線程池是你的應用程序能使用的線程的一個集合,每一個線程池都是由CLR控制的全部AppDomain共享,若是一個進程加載了多個CLR,那麼每一個CLR都有它本身的線程池,CLR初始化時,線程池中原本沒有線程,線程池的內部維護了一個隊列請求,應用程序執行一個異步時,就調用某個方法,將一個記錄項追加到線程池的隊列中,線程池的代碼從這個隊列中提取記錄項,將這個記錄項派發給一個線程池線程,若是線程池中沒有線程就建立新的線程,當任務執行後,線程並不會銷燬,返回線程池,進入空閒狀態,等待響應另外一個請求,再也不消耗額外的性能。安全
可是當一個線程閒着沒事兒一段時間後,線程會自動釋放資源,使用線程池的目的就是不用擔憂線程建立和銷燬帶來的性能損失。服務器
ThreadPool類定義的一個方法:數據結構
static Boolean QueueUserWorkItem(WaitCallback callBack,object obj);異步
方法說明:向線程池中添加一個工做項以及可選的狀態數據,而後執行此工做項,可向方法傳遞一個obj參數異步編程
代碼演示函數
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Console.WriteLine("程序開始執行"); 6 ThreadPool.QueueUserWorkItem(ComputerSort, 6); 7 Console.WriteLine("模擬其餘操做執行5s"); 8 Thread.Sleep(5000); 9 Console.WriteLine("點擊Enter退出程序"); 10 Console.ReadLine(); 11 } 12 13 private static void ComputerSort(object obj) 14 { 15 Console.WriteLine("線程池開始執行 參數={0}",obj.ToString()); 16 } 17 }
顯示結果性能
咱們發現輸出的執行順序會發生變化,是由於兩個方法相互之間在異步上運行的,Windwos調度器決定具體先調度那個線程,若是是多核CPU可能同時調度它們。spa
每一個線程都關聯兩個一個執行上下文數據結構,執行上下文包括:安全設置(壓縮棧、Principal屬性、Windows身份)、宿主設置以及邏輯調用上下文數據。線程
理想狀況下,每當一個線程使用另外一個線程(輔助線程)執行任務時,前者的執行上下文應該流向後者,確保輔助線程執行的操做都是使用的相同安全設置和宿主設置。
經過阻止執行上下文流動能夠提高應用程序的性能,尤爲是服務器應用性能提升顯著,客戶端的效果通常。
事例代碼:
1 static void Main(string[] args) 2 { 3 4 //將數據放入Main線程的邏輯上下文中 5 CallContext.LogicalSetData("Name","Tom"); 6 7 ThreadPool.QueueUserWorkItem(p => 8 { 9 Console.WriteLine("Name = {0}",CallContext.LogicalGetData("Name")); 10 }); 11 12 ExecutionContext.SuppressFlow(); 13 14 ThreadPool.QueueUserWorkItem(p => 15 { 16 Console.WriteLine("Name = {0}", CallContext.LogicalGetData("Name")); 17 }); 18 19 ExecutionContext.RestoreFlow(); 20 21 ThreadPool.QueueUserWorkItem(p => 22 { 23 Console.WriteLine("Name = {0}", CallContext.LogicalGetData("Name")); 24 }); 25 26 Console.ReadLine(); 27 28 }
對於長時間運行的計算限制操做,支持取消是一個必要的操做,.Net提供了標準的取消操做模式,不管執行操做的代碼,仍是試圖取消操做的代碼,都必須使用下面介紹的類型。
System.Threading.CancellationTokenSource------->這個對象包含了管理取消有關的全部狀態,能夠從它的Token屬性得到一個或者多個CancellationToken實例,
1 static void Main(string[] args) 2 { 3 CancellationTokenSource cts = new CancellationTokenSource(); 4 5 ThreadPool.QueueUserWorkItem(state => Count(cts.Token, 100)); 6 7 Console.WriteLine("輸入Enter中止計算"); 8 9 Console.ReadLine(); 10 11 cts.Cancel(); 12 13 Console.ReadLine(); 14 } 15 16 private static void Count(CancellationToken token,int count) 17 { 18 for (int i = 0; i <=count; i++) 19 { 20 if (token.IsCancellationRequested) 21 { 22 Console.WriteLine("接收到取消信號"); 23 break; 24 } 25 Console.WriteLine("i = {0}",i); 26 Thread.Sleep(1000); 27 } 28 }
若是願意可調用CancellationTokenSource的Register方法登記一個或者多個在取消一個CancellationTokenSource時調用的方法,要向方法傳遞一個Action<object>委託,一個要經過委託方法傳給回調,以及一個Boolean值,該值指明是否要使用調用線程的SynchroinzationContent來調用委託。
1 cts.Token.Register(() => 2 { 3 Console.WriteLine("接收到取消信號後,開始調用回調函數"); 4 });
在不少狀況下,咱們須要在過一段時間以後才取消操做,例如服務器應用程序可能會根據客戶端的請求進行計算,但必須在兩秒內響應,不管是否完成必須結束這次會話。在.NET 4.5中,CacncellationTokenSource提送了一個CancelAfter的方法
1 public void CancelAfter(int millisecondsDelay)
本章節的內容就講解到這裏,下節咱們將會繼續 線程也瘋狂-----異步編程。