概述
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); }
);