線程也瘋狂------計算限制的異步操做

前言

異步的限制操做主要做用於其餘執行線程,例如規則檢查、音頻或視頻數據轉碼以及生成圖形略縮圖,在金融和建築工程應用程序中,計算限制的操做也是十分廣泛的。編程

 

CLR線程池

線程池是你的應用程序能使用的線程的一個集合,每一個線程池都是由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)

 

本章節的內容就講解到這裏,下節咱們將會繼續 線程也瘋狂-----異步編程。

相關文章
相關標籤/搜索