線程: 每個Windows進程都有用於進入程式的進入點(entry point)的主線程(Main Thread),例如.Net framework執行程式(控制台、Windows WPF等應用程式)使用Main()方法作為程式的進入點,調用該方法時會自動建立主線程。 線程是Windows進程中的獨 ...
-
線程:
每個Windows進程都有用於進入程式的進入點(entry point)的主線程(Main Thread),例如.Net framework執行程式(控制台、Windows WPF等應用程式)使用Main()方法作為程式的進入點,調用該方法時會自動建立主線程。
線程是Windows進程中的獨立執行單元,每個線程都有一個主線程(在執行進入點時建立)並且每個線程還可以以程式方式建立新的線程。
線程的分配與啟動需要一定的時間與成本開銷,所以這個過程並不是實時的。 -
Task類:
與Thread相比,Task是更抽象的概念,MSDN說明就簡單一句:“表示非同步操作”,即為能以多線程執行的非同步操作,從net framework4.5開始,要建立實現Task後臺線程最簡單的方式就是使用靜態方法Task.Run(),在.Net Framework 4.0可以調用Task.Factory.StartNew方法,可以實現相同的效果 -
持續工作會告訴Task在完成後繼續執行後續的作業,持續工作通常由一個回調方法來實現,它會在任務完成後執行一次。 將一個Task加上持續工作又兩種方法,
- 第一種是調用Task.ContinueWith方法
- 第二種是.Net Framework4.5新增的Awaiter方法,它非常重要,因為C#5.0的非同步功能就是使用這種方式。先看程式代碼來說明
Task<int> task=Task.Run(
()=>Enumerable.Range(1,5000000).Count(n=>(n%3)==0);
var awaiter=task.GetAwaiter();
awaiter.OnCompleted(()=>
{
int result=awaiter.GetResult();
Console.WriteLine("整除3的個數有:"+Result);
Console.WriteLine("Task執行中...")
Console.ReadLine();
});
調用Task.GetAwaiter方法會返回一個awaiter(等待者)對象,它會讓先前的Task在完成或出錯之後執行一個委派,如果先前的Task出現錯誤,那麼當接續工作調用awaited.GetResult()時就會彈出例外。使用GetResult的好處是,當先前的Task出錯時,例外可以直接彈出,而不會封裝在 aggregateException中。
- Task.Delay方法在建立時間延遲之後才會完成的工作,簡單地說,它就是Thread.Sleep的非同步版本
- Parallel類 主要提供並行迴圈和區域的支持,主要有三個方法For、Foreach、Invoke,主要說一下Invoke方法,Invoke方法會簡化啟動一組並行操作,它接受一組Action[]數組。
- Async與await關鍵詞 有async修飾詞不一定有await運算符,但有await運算符一定有async修飾詞,按照微軟的建議,開發人員自己編寫的非同步方法最好也採用“Async”結尾。
- 非同步與線程池
當在應用程式中大量使用多線程技術時,首先有一點必須註意。.net framework 會在IIS維護一個線程池,當iis接受到一個請求時,就會從線程池讀取一個線程處理的請求,如果使用同步處理程式方式處理此請求,此線程直到程式處理完畢之前,都會一直為自己請求服務,並且此線程無法再為其他請求進行服務,就是所謂的封鎖。 如果線程池夠大,就沒什麼問題,不過線程池的數量是有限的,當有大量突發請求,或可應請求線程都忙於後端高延遲性網路任務時,所有線程池的線程都被封鎖,這種情況稱為線程耗盡。發生線程耗盡,IIS會開始將請求排入隊列,如果隊列已滿時,IIS就會拒絕請求,並呈現http503狀態,如果非同步應用程式正常,但是偶爾會發生http503狀態,那麼可以開課,事故為縣城靠近的情況,可以試著調高隊列長度,例如調高至一千。
註明:內容根據書籍”ASP.Net MVC5網站開發之美“整理而來