程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 線程也瘋狂------計算限制的異步操作,線程------異步

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

編輯:C#入門知識

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


參考頁面:

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線程池

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

 

本章節的內容就講解到這裡,下節我們將會繼續 線程也瘋狂-----任務。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved