이 예제에서는 Parallel.ForEach 루프를 사용하여 System.Collections.IEnumerable 또는 System.Collections.Generic.IEnumerable<T> 데이터 소스에 대한 데이터 병렬 처리가 가능하게 하는 방법을 보여 줍니다.
![]() |
---|
이 문서에서는 람다 식을 사용하여 PLINQ에 대리자를 정의합니다.C# 또는 Visual Basic의 람다 식에 익숙하지 않으면 PLINQ 및 TPL의 람다 식을 참조하십시오. |
예제
' 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();
}
}
}
ForEach 루프는 For 루프와 비슷하게 작동합니다. 즉, 소스 컬렉션이 분할되고 시스템 환경에 따라 작업이 여러 스레드에 예약됩니다. 시스템의 프로세서가 많을수록 병렬 메서드의 실행 속도가 빨라집니다. 소스 크기와 수행되는 작업의 종류에 따라 일부 소스 컬렉션의 경우에는 순차 루프가 더 빠를 수도 있습니다. 성능에 대한 자세한 내용은 데이터 및 작업 병렬 처리에서 발생할 수 있는 문제를 참조하십시오.
병렬 루프에 대한 자세한 내용은 방법: 간단한 Parallel.For 루프 작성을 참조하십시오.
제네릭이 아닌 컬렉션과 함께 ForEach를 사용하려면 다음 예제와 같이 Cast<TResult> 확장 메서드를 사용하여 컬렉션을 제네릭 컬렉션으로 변환하면 됩니다.
Parallel.ForEach(nonGenericCollection.Cast(Of Object), _
Sub(currentElement)
' ... work with currentElement
End Sub)
Parallel.ForEach(nonGenericCollection.Cast<object>(),
currentElement =>
{
});
PLINQ(병렬 LINQ)를 사용하여 IEnumerable<T> 데이터 소스의 처리를 병렬화할 수도 있습니다. PLINQ를 사용할 경우 선언적 쿼리 구문을 사용하여 루프 동작을 표현할 수 있습니다. 자세한 내용은 PLINQ(병렬 LINQ)를 참조하십시오.
코드 컴파일
이 코드를 복사하여 Visual Studio 2010 콘솔 응용 프로그램 프로젝트에 붙여넣습니다.
System.Drawing.dll에 대한 참조를 추가합니다.
F5 키를 누릅니다.