參考頁面:
http://www.yuanjiaocheng.net/webapi/create-crud-api-1.html
http://www.yuanjiaocheng.net/webapi/create-crud-api-1-get.html
http://www.yuanjiaocheng.net/webapi/create-crud-api-1-post.html
http://www.yuanjiaocheng.net/webapi/create-crud-api-1-put.html
http://www.yuanjiaocheng.net/webapi/create-crud-api-1-delete.html
異步的限制操作主要作用於其他執行線程,例如規則檢查、音頻或視頻數據轉碼以及生成圖形略縮圖,在金融和建築工程應用程序中,計算限制的操作也是十分普遍的。
線程池是你的應用程序能使用的線程的一個集合,每個線程池都是由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可能同時調度它們。
每個線程都關聯兩個一個執行上下文數據結構,執行上下文包括:安全設置(壓縮棧、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)
本章節的內容就講解到這裡,下節我們將會繼續 線程也瘋狂-----任務。