Pętla Parallel.For używa ThreadPool do wykonania pracy w pętli poprzez wywołanie delegata raz na każdą iterację pętli.
Ogólna idea jak Parallel.For prace można przedstawić w następujący sposób:
public static void MyParallelFor(int inclusiveLowerBound, int exclusiveUpperBound, Action<int> body)
{
// Get the number of processors, initialize the number of remaining
// threads, and set the starting point for the iteration.
int numProcs = Environment.ProcessorCount;
int remainingWorkItems = numProcs;
int nextIteration = inclusiveLowerBound;
using (ManualResetEvent mre = new ManualResetEvent(false))
{
// Create each of the work items.
for (int p = 0; p < numProcs; p++)
{
ThreadPool.QueueUserWorkItem(delegate
{
int index;
while ((index = Interlocked.Increment(ref nextIteration) - 1) < exclusiveUpperBound)
body(index);
if (Interlocked.Decrement(ref remainingWorkItems) == 0)
mre.Set();
});
}
// Wait for all threads to complete.
mre.WaitOne();
}
}
Parallel.For zwraca ParallelLoopResult typ wartości, która zawiera szczegółowe informacje na temat zakończonej pętlą. Jednym z jego przeciążeń jest:
public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body);
Ważne jest, aby zdać sobie sprawę, że wykonanie równoległe nie zawsze jest szybsze niż wykonanie seryjne. Aby zdecydować, czy używać równolegle, czy nie, musisz oszacować nakład pracy, który będzie wykonywany w przeliczeniu na pętlę. Jeśli rzeczywista praca wykonywana przez pętlę jest niewielka w stosunku do kosztu synchronizacji wątku, lepiej użyć zwykłej pętli.
Jest to jeden przykład, kiedy seryjny do wykonywania pętli jest szybsza, że równolegle:
static void Main(string[] args)
{
Action<int> action = new Action<int>(SimpleMethod);
// ordinary For loop performance estimation
var sw = Stopwatch.StartNew();
for(int i = 0; i < 1000; i++)
action(i);
Console.WriteLine("{0} sec.", sw.Elapsed.TotalSeconds);
// parallel For loop performance estimation
sw = Stopwatch.StartNew();
Parallel.For(0, 1000, action);
Console.WriteLine("{0} sec.", sw.Elapsed.TotalSeconds);
}
static void SimpleMethod(int index)
{
int d = 1;
int result = index/d;
}
wyjściowa:
0.0001963 sec.
0.0346729 sec.
Tutaj jest naprawdę dobry darmowy ebook z Microsoft, który obejmuje ten temat " [Wzory programowania równoległego: Rozumienie i stosowanie równoległych wzorców w środowisku .NET Framework 4] (https://www.microsoft.com/en-us/download/details.aspx?id=19222) " –