[C#.NET][TPL] 初探 TPL 用法

[C#.NET][TPL] 初探 TPL 用法

在.NET 4.0 版本的執行緒處理中,微軟增加了平行運算函式庫 Task Parallel Library (TPL),主要是增加  System.Threading.Tasks 命名空間中的API,請參考

http://msdn.microsoft.com/zh-tw/library/dd460717%28v=vs.100%29.aspx

不過,要使用平行運算前,要先理解自己要開發的工作流程是屬於串行流程還是平行流程,若工作流程是屬於串行流程,在這種情況下使用平行運算很有可能會讓程式運行速度變慢;當然,也不是所有的流程使用執行緒處理後一定會變快,一定要瞭解自己的工作流程。

 

下圖,表示串行流程,區塊內的工作必須有順序性的,在這情況下 TPL 幫不了太大的忙

image

 

如下圖,區塊內的工作,跟其他區塊沒有關係,用 TPL 可感覺明顯的優化。

image

 

Task / Task.Factory 會將多個工作分派到每一個CPU。

Parallel.For /Parallel.ForEach  會將單一工作切成好幾塊,並分派到每一個CPU。

比如:發送簡訊給通訊錄裡的手機,發送機制沒有卡到其他流程

 

串行運算:

如下列程式碼,迴圈內的工作,沒有順序關係也不需要等待彼此。

for (int i = 0; i < contact.Peoples.Count; i++)
{
    SMS.SendText(contact.Peoples[i].CellPhone);
}

 

將串行運算轉換為平行運算:

如下程式碼,可將串行運算裡的迴圈,由 TPL 底層自動拆成多個工作,同时指派給多個CPU,在程式碼撰寫上不需要花費太多的力氣。

 

Parallel.For(0, contact.Peoples.Count, i => { SMS.SendText(contact.Peoples[i].CellPhone); });

 

 

平行運算示意圖:

 

 

image

 

為什麼要用TPL? System.Threading.Thread Class  & System.Threading.TheadPool Class  V.S System.Thread.Tasks.Task Class

TPL(System.Thread.Task)  跟傳統執行緒 (System.Threading) 的執行結果沒有太大的異處,在沒有使用 TPL 以前,需要一堆程式碼來處理執行緒的『完成』、『取消』、『失敗』通知動作,但是 TPL 可以我們省掉了不少功夫,雖然兩者的運行結果相同,但底層的運行方式對軟體的效能能夠提昇,當然,要有效能上的提升前提之下是要有正確的流程。

有關執行緒的硬底子,可以參考
http://tl.zxhsd.com/kgsm/ts/big5/2012/02/02/2167932.shtml

 

.NET 3.5 執行緒寫法

ThreadPool.QueueUserWorkItem(_ =>
{
    //TODO:要做的事
});

 

 

.NET 4.0 TPL 寫法

Task t = new Task(() => 
{ 
    //TODO:要做的事 
}); 

Task.Factory.StartNew(() => 
{ 
    //TODO:要做的事 
}); 

Parallel.Invoke(() => 
{ 
    //TODO:要做的事 
});


.NET 4.5 TPL 寫法

Task.Run(() =>
{
    //TODO:要做的事
});

 

可以看出在用法上傳統執行緒的用法跟 TPL 沒什麼兩樣,但其實在實作細節上 TPL 可以省掉很多很多的工,這在後面會再提到。

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo