Partager via


Comment : écrire une boucle Parallel.ForEach comprenant des variables de thread local

L'exemple suivant indique comment écrire une méthode ForEach qui utilise des variables de thread local. Lorsqu'une boucle ForEach s'exécute, elle divise sa collection source en plusieurs partitions. Chaque partition obtiendra sa propre copie de la variable de « thread local ». (Le terme « thread local » est légèrement inexact ici, parce que dans certains cas, deux partitions peuvent s'exécuter sur le même thread.)

Le code et les paramètres dans cet exemple ressemblent de près à la méthode For correspondante. Pour plus d'informations, consultez Comment : écrire une boucle Parallel.For comprenant des variables locales de thread.

Exemple

Pour utiliser une variable de thread local dans une boucle ForEach, vous devez utiliser la version de la méthode qui prend deux paramètres de type. Le premier paramètre spécifie le type de l'élément source et le deuxième paramètre spécifie le type de la variable de thread local.

Le premier paramètre d'entrée est la source de données, et le deuxième est la fonction qui initialisera la variable de thread local. Le troisième paramètre d'entrée est un Func<T1, T2, T3, TResult> appelé par la boucle parallèle sur chaque itération. Vous fournissez le code pour le délégué et la boucle passe dans les paramètres d'entrée. Les paramètres d'entrée sont l'élément actuel, une variable ParallelLoopState qui vous permet d'examiner l'état de la boucle, et la variable de thread local. Vous retournez la variable de thread local et la méthode la passe ensuite à l'itération suivante sur cette partition. Cette variable est distincte sur toutes les partitions de la boucle.

Le dernier paramètre d'entrée de la méthode ForEach est le délégué Action<T> que la méthode appellera lorsque toutes les boucles seront terminées. La méthode fournit la dernière valeur de la variable de thread local pour ce thread (ou partition de boucle), et vous fournissez le code qui capture la dernière valeur et exécute n'importe quelle action obligatoire afin de combiner le résultat de cette partition avec les résultats d'autres partitions. Étant donné que le type délégué est un Action<T>, il n'y a aucune valeur de retour.

' 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 paramemter is the type of the source elements
        ' Second type parameter is the type of the local data (subtotal)
        Parallel.ForEach(Of Integer, Long)(nums, Function() 0,
                                           Function(elem, loopState, subtotal)
                                               subtotal += nums(elem)
                                               Return subtotal
                                           End Function,
                                            Sub(finalResult)
                                                Interlocked.Add(total, finalResult)
                                            End Sub)

        Console.WriteLine("The result of Parallel.ForEach is {0}", total)
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub
End Module
namespace ThreadLocalForEach
{
    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 local data (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 += nums[j]; //modify local variable
                                            return subtotal; // value to be passed to next iteration
                                        },
                // Method to be executed when all loops have completed.
                // finalResult is the final value of subtotal. supplied by the ForEach method.
                                        (finalResult) => Interlocked.Add(ref total, finalResult)
                                        );

            Console.WriteLine("The total from Parallel.ForEach is {0}", total);
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

Voir aussi

Tâches

Comment : écrire une boucle Parallel.For comprenant des variables locales de thread

Concepts

Parallélisme de données (bibliothèque parallèle de tâches)

Expressions lambda en PLINQ et dans la bibliothèque parallèle de tâches