Postupy: Zápis smyčky Parallel.ForEach s využitím místních proměnných oddílů
Následující příklad ukazuje, jak napsat metodu ForEach , která používá proměnné partition-local. Při provedení smyčky ForEach dochází k rozdělení kolekce prostředků na několik oddílů. Každý oddíl má vlastní kopii místní proměnné oddílu. Místní proměnná oddílu se podobá místní proměnné vlákna s tím rozdílem, že na jednom vlákně může běžet více oddílů.
Kód a parametry uvedené v tomto příkladu se velmi podobají příslušné metodě For. Další informace naleznete v tématu Postupy: Zápis parallel.For Loop s vlákny místní proměnné.
Chcete-li ve smyčce použít místní proměnnou oddílu ForEach , musíte volat jedno z přetížení metody, které přebírá dva parametry typu. První parametr typu , TSource
, určuje typ zdrojového elementu a druhý typ parametr, TLocal
určuje typ partition-local proměnné.
Příklad
Následující příklad volá Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) přetížení pro výpočet součtu pole jednoho milionu prvků. Toto přetížení má čtyři parametry:
source
, což je zdroj dat. Musí implementovat IEnumerable<T>. Zdroj dat v našem příkladu je objekt jednoho milionu členůIEnumerable<Int32>
vrácený metodou Enumerable.Range .localInit
nebo funkci, která inicializuje místní proměnnou oddílu. Tato funkce se volá jednou pro každý oddíl, ve kterém se Parallel.ForEach operace provede. Náš příklad inicializuje místní proměnnou oddílu na nulu.body
Func<T1,T2,T3,TResult>, která je vyvolána paralelní smyčkou pro každou iteraci smyčky. Jeho podpis jeFunc\<TSource, ParallelLoopState, TLocal, TLocal>
. Zadáte kód pro delegáta a smyčka předává vstupní parametry, které jsou:Aktuální prvek IEnumerable<T>.
Proměnná ParallelLoopState , kterou můžete použít v kódu delegáta k prozkoumání stavu smyčky.
Místní proměnná oddílu.
Váš delegát vrátí místní proměnnou oddílu, která se pak předá další iteraci smyčky, která se provede v daném oddílu. Každý oddíl smyčky udržuje samostatnou instanci této proměnné.
V tomto příkladu delegát přidá hodnotu každého celého čísla do místní proměnné oddílu, která udržuje průběžný součet hodnot celočíselných prvků v tomto oddílu.
localFinally
Action<TLocal>
, delegát, který Parallel.ForEach vyvolá, když se operace smyčky v každém oddílu dokončily. Metoda Parallel.ForEach předává delegátaAction<TLocal>
konečnou hodnotu proměnné partition-local pro tento oddíl smyčky a zadáte kód, který provede požadovanou akci pro kombinování výsledku z tohoto oddílu s výsledky z ostatních oddílů. Tento delegát lze vyvolat souběžně s několika úkoly. Z tohoto důvodu příklad používá metodu Interlocked.Add(Int32, Int32) k synchronizaci přístupu ktotal
proměnné. Vzhledem k tomu, že delegát je typu Action<T>, neexistuje žádná návratová hodnota.
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Test
{
static void Main()
{
int[] nums = Enumerable.Range(0, 1000000).ToArray();
long total = 0;
// First type parameter is the type of the source elements
// Second type parameter is the type of the thread-local variable (partition subtotal)
Parallel.ForEach<int, long>(
nums, // source collection
() => 0, // method to initialize the local variable
(j, loop, subtotal) => // method invoked by the loop on each iteration
{
subtotal += j; //modify local variable
return subtotal; // value to be passed to next iteration
},
// Method to be executed when each partition has completed.
// finalResult is the final value of subtotal for a particular partition.
(finalResult) => Interlocked.Add(ref total, finalResult));
Console.WriteLine("The total from Parallel.ForEach is {0:N0}", total);
}
}
// The example displays the following output:
// The total from Parallel.ForEach is 499,999,500,000
' How to: Write a Parallel.ForEach Loop That Has Thread-Local Variables
Imports System.Threading
Imports System.Threading.Tasks
Module ForEachThreadLocal
Sub Main()
Dim nums() As Integer = Enumerable.Range(0, 1000000).ToArray()
Dim total As Long = 0
' First type parameter is the type of the source elements
' Second type parameter is the type of the thread-local variable (partition subtotal)
Parallel.ForEach(Of Integer, Long)(nums, Function() 0,
Function(elem, loopState, subtotal)
subtotal += elem
Return subtotal
End Function,
Sub(finalResult)
Interlocked.Add(total, finalResult)
End Sub)
Console.WriteLine("The result of Parallel.ForEach is {0:N0}", total)
End Sub
End Module
' The example displays the following output:
' The result of Parallel.ForEach is 499,999,500,000
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro