概述
Microsoft Parallel Extensions to the .NET Framework 3.5是一個託管編程模型,用於資料並行化和任務並行化,並可對統一在共同的工作發送器之下的並行硬體進行協調。 Parallel Extensions to the .NET Framework 3.5使開發人員更容易編寫出充分發揮並行硬體的優勢的程式,不但能隨著處理器數量的增長而提高效能,而且避免了許多舊有並發編程模型的複雜性。
你可以從這裡下載Microsoft Parallel Extensions to the .NET Framework 3.5 June 2008 CTP版本,安裝後會註冊一個System.Threading.dll程式集到GAC中。Parallel Extensions主要由兩部分組成:Task Parallel Library(TPL)和Parallel LINQ (PLINQ),它們將會整合在.NET Framework 4.0中。
簡單調用
在開始之前,我們不妨停下來思考幾個問題:如果有多個線程在同一時間訪問同一個變數,它們之間可能會互相影響,該如何解決?如果有多個線程同時鎖住了一些資源,由於互相等待而造成死結,該如何解決?如果覺的這些問題很難解決,那就不要思考了,有了Parallel.Invoke,無需再去考慮這些令人頭疼的問題,我們先定義三個任務:
private void Task1(){ Thread.Sleep(1000);}private void Task2(){ Thread.Sleep(2000);}private void Task3(){ Thread.Sleep(3000);}
並行調用這三個任務,只需要一句話:
Parallel.Invoke(Task1, Task2, Task3);
除此之外,還可以把所有的任務放在一個Action資料群組中,再進行調用,如下程式碼片段,這在某些情境中會非常的有用,我們在設計階段無需考慮最終運行時將會有多少個任務會執行:
Action[] actions = { Task1, Task2, Task3 };Parallel.Invoke(actions);
我們不妨對Parallel.Invoke做一個簡單的測試,如下程式碼片段所示:
private long InvokeSequential(){ Stopwatch watch = new Stopwatch(); watch.Start(); Task1(); Task2(); Task3(); watch.Stop(); return watch.ElapsedMilliseconds;}private long InvokeParallel(){ Stopwatch watch = new Stopwatch(); watch.Start(); Parallel.Invoke(Task1, Task2, Task3); watch.Stop(); return watch.ElapsedMilliseconds;}private long InvokeParallelArray(){ Stopwatch watch = new Stopwatch(); watch.Start(); Action[] actions = { Task1, Task2, Task3 }; Parallel.Invoke(actions); watch.Stop(); return watch.ElapsedMilliseconds;}
來看看最後的結果:
迴圈調用
迴圈執行某件事情應該是我們編程中經常遇到的問題,但是之前所有的迴圈只能順序的進行執行,如下面這段代碼,再平常不過了:
for (int i = 0; i < 10; i++){ Compute(i);}
在Parallel Extensions中,可以使用Parallel.For來並行的執行迴圈任務:
Parallel.For(0, 10, delegate (int i){ Compute(i); } );
甚至有了Lambda運算式,還可以更簡單的編寫為:
Parallel.For(0, 10, i => { Compute(i);} );
現在,我們再來做一個簡單的測試,代碼如下:
private static long SequentialForLoop(){ Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < 10; i++) { Compute(i); } watch.Stop(); return watch.ElapsedMilliseconds;}private static long ParallelForLoop(){ Stopwatch watch = new Stopwatch(); watch.Start(); Parallel.For(0, 10, i => { Compute(i);} ); watch.Stop(); return watch.ElapsedMilliseconds;}private static void Compute(int i){ Thread.Sleep(200 * i);}
測試結果如下:
類似的在Parallel中還提供了Parallel.ForEach方法,如所示:
我們使用類似於如下的代碼來使用該方法:
List<int> data = new List<int> { 1, 2, 3, 4, 5 };Parallel.ForEach( data, i => { Compute(i); } );總結
以上簡單的介紹了Task Parallel Library中的Parallel, 希望對大家有所協助。