Partager via


Comment : écrire une boucle Parallel.ForEach simple

Cet exemple indique comment utiliser une boucle Parallel.ForEach pour permettre le parallélisme des données sur toute source de données System.Collections.IEnumerable ou System.Collections.Generic.IEnumerable<T>.

RemarqueRemarque

Cette documentation utilise des expressions lambda pour définir des délégués en PLINQ.Si les expressions lambda en C# ou Visual Basic ne vous sont pas familières, consultez Expressions lambda en PLINQ et dans la bibliothèque parallèle de tâches.

Exemple

' How to: Write a Simple Parallel.ForEach Loop
' IMPORTANT!!!: Add reference to System.Drawing.dll
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Drawing

Module ForEachDemo

    Sub Main()
        ' A simple source for demonstration purposes. Modify this path as necessary.
        Dim files As String() = System.IO.Directory.GetFiles("C:\Users\Public\Pictures\Sample Pictures", "*.jpg")
        Dim newDir As String = "C:\Users\Public\Pictures\Sample Pictures\Modified"
        System.IO.Directory.CreateDirectory(newDir)

        ' Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body)
        ' Be sure to add a reference to System.Drawing.dll.
        Parallel.ForEach(files, Sub(currentFile)
                                    ' The more computational work you do here, the greater 
                                    ' the speedup compared to a sequential foreach loop.
                                    Dim filename As String = System.IO.Path.GetFileName(currentFile)
                                    Dim bitmap As New System.Drawing.Bitmap(currentFile)

                                    bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone)
                                    bitmap.Save(System.IO.Path.Combine(newDir, filename))

                                    ' Peek behind the scenes to see how work is parallelized.
                                    ' But be aware: Thread contention for the Console slows down parallel loops!!!

                                    Console.WriteLine("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId)
                                    'close lambda expression and method invocation
                                End Sub)


        ' Keep the console window open in debug mode.
        Console.WriteLine("Processing complete. Press any key to exit.")
        Console.ReadKey()
    End Sub
End Module
namespace ForEachDemo
{
    using System;
    using System.Drawing; // requires system.Drawing.dll
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;

    class SimpleForEach
    {
        static void Main()
        {
            // A simple source for demonstration purposes. Modify this path as necessary.
            string[] files = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg");
            string newDir = @"C:\Users\Public\Pictures\Sample Pictures\Modified";
            System.IO.Directory.CreateDirectory(newDir);

            //  Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body)
            Parallel.ForEach(files, currentFile =>
            {
                // The more computational work you do here, the greater 
                // the speedup compared to a sequential foreach loop.
                string filename = System.IO.Path.GetFileName(currentFile);
                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(currentFile);

                bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
                bitmap.Save(System.IO.Path.Combine(newDir, filename));

                // Peek behind the scenes to see how work is parallelized.
                // But be aware: Thread contention for the Console slows down parallel loops!!!
                Console.WriteLine("Processing {0} on thread {1}", filename,
                                    Thread.CurrentThread.ManagedThreadId);

            } //close lambda expression
                 ); //close method invocation

            // Keep the console window open in debug mode.
            Console.WriteLine("Processing complete. Press any key to exit.");
            Console.ReadKey();
        }
    }
}

Une boucle ForEach fonctionne comme une boucle For. La collection source est partitionnée et le travail est planifié sur plusieurs threads en fonction de l'environnement système. Plus les processeurs du système sont nombreux, plus l'exécution de la méthode parallèle est rapide. Pour certaines collections source, une boucle séquentielle peut être plus rapide, en fonction de la taille de la source et du genre de travail exécuté. Pour plus d'informations sur les performances, consultez Pièges potentiels dans le parallélisme des données et des tâches

Pour plus d'informations sur les boucles parallèles, consultez Comment : écrire une boucle Parallel.For simple.

Pour utiliser ForEach avec une collection non générique, vous pouvez utiliser la méthode d'extension Cast<TResult> pour convertir la collection en collection générique, comme l'illustre l'exemple suivant :

Parallel.ForEach(nonGenericCollection.Cast(Of Object), _
                 Sub(currentElement)
                     ' ... work with currentElement
                 End Sub)
Parallel.ForEach(nonGenericCollection.Cast<object>(),
    currentElement =>
    {
    });

Vous pouvez également utiliser Parallel LINQ (PLINQ) pour paralléliser le traitement des sources de données IEnumerable<T>. PLINQ vous permet d'utiliser la syntaxe de requête déclarative pour exprimer le comportement de la boucle. Pour plus d'informations, consultez Parallel LINQ (PLINQ).

Compilation du code

  • Copiez et collez ce code dans un projet Application console 2010 Visual Studio et appuyez sur F5.

  • Ajoutez une référence à System.Drawing.dll.

  • Appuyez sur F5.

Voir aussi

Concepts

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

Programmation parallèle dans le .NET Framework

Parallel LINQ (PLINQ)