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 partíció-helyi ForEach változókat használó metódust. ForEach Egy ciklus végrehajtásakor a forrásgyűjteményt 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ók hasonlóak a szál helyi változóihoz, 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ó : How to: Write a Parallel.For Loop with Thread-Local Variables.

Ha partíció-helyi változót szeretne használni egy ForEach ciklusban, meg kell hívnia a metódus túlterheléseinek egyikét, amely két típusparamétert vesz igénybe. Az első típusparaméter, TSourcea forráselem típusát, a második típusparaméter TLocalpedig a partíció-helyi változó típusát adja meg.

Példa

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

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

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

  • body, amelyet Func<T1,T2,T3,TResult> a párhuzamos hurok hív meg a ciklus minden iterációján. Az aláírása .Func\<TSource, ParallelLoopState, TLocal, TLocal> Meg kell adnia a delegált kódját, és a hurok a bemeneti paraméterekben halad át, 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.

  • localFinally, egy Action<TLocal> meghatalmazott, amelyet a Parallel.ForEach rendszer meghív, amikor az egyes partíciókban végrehajtott ciklusműveletek befejeződtek. A Parallel.ForEach metódus átadja a Action<TLocal> delegáltnak a partíció-helyi változó végső értékét ehhez a hurokpartícióhoz, és megadja azt a kódot, amely végrehajtja a szükséges műveletet az eredmény és a többi partíció eredményeinek egyesítéséhez. Ezt a meghatalmazottat egyszerre több tevékenység is meghívhatja. Emiatt a példa a Interlocked.Add(Int32, Int32) metódus használatával szinkronizálja a total változóhoz való hozzáférést. 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 {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

Lásd még