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


Útmutató: Párhuzamos.For loop írása Thread-Local változókkal

Ez a példa bemutatja, hogyan tárolhatja és lekérheti az állapotot a ciklus által létrehozott különálló feladatokban szál-helyi változók használatával For . A szálalapú adatok használatával elkerülheti a nagy számú hozzáférés szinkronizálásának többletterhelését a megosztott állapothoz. Ahelyett, hogy az egyes iterációkban megosztott erőforrásba ír, kiszámítja és tárolja az értéket, amíg a tevékenység összes iterációja be nem fejeződik. Ezután egyszer megírhatja a végeredményt a megosztott erőforrásba, vagy átadhatja egy másik metódusnak.

Példa

Az alábbi példa egy For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) egymillió elemet tartalmazó tömb értékeinek összegének kiszámítására hívja meg a metódust. Az egyes elemek értéke megegyezik az indexével.

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

class Test
{
    static void Main()
    {
        int[] nums = Enumerable.Range(0, 1_000_000).ToArray();
        long total = 0;

        // Use type parameter to make subtotal a long, not an int
        Parallel.For<long>(0, nums.Length, () => 0,
            (j, loop, subtotal) =>
            {
                subtotal += nums[j];
                return subtotal;
            },
            subtotal => Interlocked.Add(ref total, subtotal));

        Console.WriteLine($"The total is {total:N0}");
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}
'How to: Write a Parallel.For Loop That Has Thread-Local Variables

Imports System.Threading
Imports System.Threading.Tasks

Module ForWithThreadLocal

    Sub Main()
        Dim nums As Integer() = Enumerable.Range(0, 1000000).ToArray()
        Dim total As Long = 0

        ' Use type parameter to make subtotal a Long type. Function will overflow otherwise.
        Parallel.For(Of Long)(0, nums.Length, Function() 0, Function(j, [loop], subtotal)
                                                                subtotal += nums(j)
                                                                Return subtotal
                                                            End Function, Function(subtotal) Interlocked.Add(total, subtotal))

        Console.WriteLine("The total is {0:N0}", total)
        Console.WriteLine("Press any key to exit")
        Console.ReadKey()
    End Sub

End Module

Minden metódus első két paramétere For határozza meg a kezdő és záró iterációs értékeket. A metódus ezen túlterhelése esetén a harmadik paraméter az, ahol inicializálja a helyi állapotot. Ebben az összefüggésben a helyi állapot azt a változót jelenti, amelynek élettartama az aktuális szál ciklusának első iterációja előtt, az utolsó iteráció utánra terjed ki.

A harmadik paraméter Func<TResult>TResult típusa a szál helyi állapotát tároló változó típusa. Típusát az általános metódus meghívásakor For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) megadott általános típusargumentum határozza meg, amely ebben az esetben az Int64. A típusargumentum tájékoztatja a fordítót a szál helyi állapotának tárolására használt ideiglenes változó típusáról. Ebben a példában a kifejezés () => 0 (vagy Function() 0 a Visual Basicben) nullára inicializálja a szál-helyi változót. Ha az általános típusargumentum hivatkozástípus vagy felhasználó által definiált értéktípus, a kifejezés a következőképpen fog kinézni:

() => new MyClass()  
Function() new MyClass()  

A negyedik paraméter határozza meg a hurok logikáját. Delegált vagy lambda kifejezésnek kell lennie, amelynek szignatúrája Func<int, ParallelLoopState, long, long> C# nyelven vagy Func(Of Integer, ParallelLoopState, Long, Long) a Visual Basic nyelven. Az első paraméter a hurok adott iterációjának hurokszámlálójának értéke. A második egy ParallelLoopState objektum, amely a hurokból való kibontásra használható; ezt az objektumot az Parallel osztály biztosítja a hurok minden előfordulásához. A harmadik paraméter a szál helyi változója. Az utolsó paraméter a visszatérési típus. Ebben az esetben a típus Int64, mert ez az a típus, amelyet a For típusargumentumban adtunk meg. Ennek a változónak a neve subtotal, és a lambda kifejezés adja vissza. A visszatérési értéket használják a subtotal inicializálására a ciklus minden további iterációján. Azt is gondolhatja, hogy ez az utolsó paraméter egy olyan érték, amelyet átad minden egyes iterációnak, majd az utolsó iteráció befejezésekor átadja a localFinally delegáltnak.

Az ötödik paraméter határozza meg az egyszer meghívott metódust, miután az adott szál összes iterációja befejeződött. A bemeneti argumentum típusa ismét megfelel a metódus típusargumentumának For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) és a lambda törzskifejezés által visszaadott típusnak. Ebben a példában az érték az osztály hatókörében lévő változóhoz lesz hozzáadva szálbiztos módon a Interlocked.Add metódus meghívásával. A szálhoz kötött változó használatával elkerültük ennek az osztályváltozónak az írását a ciklus minden iterációján.

További információ a lambdakifejezések használatáról: Lambda Expressions in PLINQ and TPL.

Lásd még