Megosztás a következőn keresztül:


Útmutató: Parallel.ForEach hurok írása partíció-helyi változókkal

Az alábbi példa bemutatja, hogyan írhat egy partíció-helyi változókat használó ForEach metódust. Amikor egy ForEach ciklus fut, a forrásgyűjteményét több partícióra osztja. Minden partíció saját másolatot készít a partíció helyi változójáról. A partíció-helyi változó hasonlít egy szál-helyi változóhoz, azzal a kivételrel, hogy több partíció is futtatható egyetlen szálon.

A példában szereplő kód és paraméterek szorosan hasonlítanak a megfelelő For metódusra. További információért lásd: Hogyan írjunk Parallel.For ciklust Thread-Local változókkal.

Ha particionálási helyi változót szeretne használni egy ForEach ciklusban, meg kell hívnia az egyik metódus túlterhelését, amely két típusparamétert vesz igénybe. Az első típusparaméter (TSource) a forráselem típusát adja meg, a második típusparaméter pedig a TLocal, a partíció helyi változójának típusát adja meg.

Példa

Az alábbi példa a Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) túlterhelést hívja meg egy millió elemből álló tömb összegének kiszámításához. Ennek a túlterhelésnek négy paramétere van:

  • source, amely az adatforrás. Implementálnia kell IEnumerable<T>. A példánkban szereplő adatforrás a Enumerable.Range metódus által visszaadott egymillió tagú IEnumerable<Int32> objektum.

  • localInit, vagy a partíció-helyi változót inicializáló függvény. Ezt a függvényt minden olyan partícióhoz meghívjuk, amelyben a Parallel.ForEach művelet fut. A példánk a partíció-helyi változót nullára inicializálja.

  • bodyegy Func<T1,T2,T3,TResult>, amelyet a ciklus minden iterációján a párhuzamos hurok hív meg. Aláírása Func\<TSource, ParallelLoopState, TLocal, TLocal>. Ön adja meg a delegált kódot, és a hurok továbbítja a bemeneti paramétereket, amelyek a következők:

    • A IEnumerable<T>aktuális eleme.

    • Egy ParallelLoopState változó, amelyet a meghatalmazott kódjában használhat a ciklus állapotának vizsgálatához.

    • A partíció helyi változója.

    A meghatalmazott visszaadja a partíció-helyi változót, amelyet a rendszer a ciklus következő iterációjának ad vissza, amely az adott partíción fut. Minden hurokpartíció ennek a változónak egy külön példányát tartja fenn.

    A példában a meghatalmazott hozzáadja az egyes egész számok értékét a partíció-helyi változóhoz, amely a partíció egész elemeinek értékeinek futó összegét tartja fenn.

  • localFinallyegy Action<TLocal> delegált, amelyet a Parallel.ForEach hív meg, amikor az egyes partíciók ciklusműveletei befejeződtek. A Parallel.ForEach metódus átadja a Action<TLocal> delegáltnak a partíció helyi változójának végső értékét ehhez a hurokpartícióhoz, és Ön adja meg azt a kódot, amely végrehajtja a szükséges műveletet a partíció eredményének más partíciók eredményeivel való összekapcsolásához. Ezt a delegált függvényt egyszerre több feladat is meghívhatja. Emiatt a példa a Interlocked.Add(Int32, Int32) metódust használja a total változóhoz való hozzáférés szinkronizálásához. Mivel a delegált típusa egy Action<T>, nincs visszatérési érték.

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 {total:N0}");
    }
}
// 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

Lásd még