Cómo: Escribir un bucle Parallel.ForEach simple
En este ejemplo, se muestra cómo se usa un bucle Parallel.ForEach para habilitar el paralelismo de datos en cualquier origen de datos System.Collections.IEnumerable o System.Collections.Generic.IEnumerable<T>.
Nota |
---|
En esta documentación, se utilizan expresiones lambda para definir delegados en la PLINQ.Si no está familiarizado con las expresiones lambda en C# o Visual Basic, vea Expresiones lambda en PLINQ y TPL. |
Ejemplo
' 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();
}
}
}
Un bucle ForEach funciona como un bucle For. Se crea una partición de la colección de origen y el trabajo se programa en varios subprocesos en función del entorno del sistema. Cuantos más procesadores tenga el sistema, más rápido se ejecutará el método paralelo. En algunas colecciones de origen, puede resultar más rápido un bucle secuencial, en función del tamaño del origen y del tipo de trabajo que se realice. Para obtener más información acerca del rendimiento, vea Problemas potenciales en el paralelismo de datos y tareas
Para obtener más información acerca de los bucles paralelos, vea Cómo: Escribir un bucle Parallel.For simple
Para usar ForEach con una colección no genérica, puede emplear el método de extensión Cast<TResult> para convertir la colección en una colección genérica, como se muestra en el ejemplo siguiente:
Parallel.ForEach(nonGenericCollection.Cast(Of Object), _
Sub(currentElement)
' ... work with currentElement
End Sub)
Parallel.ForEach(nonGenericCollection.Cast<object>(),
currentElement =>
{
});
Puede usar también Parallel LINQ (PLINQ) con el fin de paralelizar el procesamiento de los orígenes de datos IEnumerable<T>. PLINQ permite usar una sintaxis de consulta declarativa para expresar el comportamiento del bucle. Para obtener más información, vea Parallel LINQ (PLINQ).
Compilar el código
Copie y pegue este código en un proyecto de aplicación de consola de Visual Studio 2010.
Agregue una referencia a System.Drawing.dll.
Presione F5.
Vea también
Conceptos
Paralelismo de datos (Task Parallel Library)