參考頁面:
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)
本章節的內容就講解到這裡,下節我們將會繼續 線程也瘋狂-----任務。