다음을 통해 공유


방법: Parallel.For 또는 ForEach 루프 취소

Parallel.ForParallel.ForEach 메서드는 취소 토큰을 사용한 취소 기능을 지원합니다. 일반적인 취소에 대한 자세한 내용은 취소를 참조하십시오. 병렬 루프에서는 ParallelOptions 매개 변수로 메서드에 CancellationToken을 제공한 다음 병렬 호출을 try-catch 블록 안에 넣습니다.

예제

다음 예제에서는 Parallel.ForEach에 대한 호출을 취소하는 방법을 보여 줍니다. Parallel.For 호출에도 동일한 방법을 적용할 수 있습니다.

' How to: Cancel a Parallel.For or ForEach Loop

Imports System.Threading
Imports System.Threading.Tasks

Module CancelParallelLoops

    Sub Main()

        Dim nums() As Integer = Enumerable.Range(0, 10000000).ToArray()
        Dim cts As New CancellationTokenSource

         ' Use ParallelOptions instance to store the CancellationToken
        Dim po As New ParallelOptions
        po.CancellationToken = cts.Token
        po.MaxDegreeOfParallelism = System.Environment.ProcessorCount
        Console.WriteLine("Press any key to start. Press 'c' to cancel.")
        Console.ReadKey()

        ' Run a task so that we can cancel from another thread.
        Dim t As Task = Task.Factory.StartNew(Sub()
                                                  If Console.ReadKey().KeyChar = "c"c Then
                                                      cts.Cancel()
                                                  End If
                                                  Console.WriteLine(vbCrLf & "Press any key to exit.")
                                              End Sub)

        Try

            ' The error "Exception is unhandled by user code" will appear if "Just My Code" 
            ' is enabled. This error is benign. You can press F5 to continue, or disable Just My Code.
            Parallel.ForEach(nums, po, Sub(num)
                                           Dim d As Double = Math.Sqrt(num)
                                           Console.CursorLeft = 0
                                           Console.Write("{0:##.##} on {1}", d, Thread.CurrentThread.ManagedThreadId)
                                           po.CancellationToken.ThrowIfCancellationRequested()
                                       End Sub)

        Catch e As OperationCanceledException
            Console.WriteLine(e.Message)
        End Try

        Console.ReadKey()

    End Sub
End Module
namespace CancelParallelLoops
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;

    class Program
    {
        static void Main()
        {
            int[] nums = Enumerable.Range(0, 10000000).ToArray();
            CancellationTokenSource cts = new CancellationTokenSource();

           // Use ParallelOptions instance to store the CancellationToken
            ParallelOptions po = new ParallelOptions();
            po.CancellationToken = cts.Token;
            po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
            Console.WriteLine("Press any key to start. Press 'c' to cancel.");
            Console.ReadKey();

            // Run a task so that we can cancel from another thread.
            Task.Factory.StartNew(() =>
            {
                if (Console.ReadKey().KeyChar == 'c')
                    cts.Cancel();
                Console.WriteLine("press any key to exit");
            });

            try
            {
                Parallel.ForEach(nums, po, (num) =>
                {
                    double d = Math.Sqrt(num);
                    Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
                    po.CancellationToken.ThrowIfCancellationRequested();
                });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadKey();
        }
    }
}

취소를 알리는 토큰이 ParallelOptions 인스턴스에 지정된 토큰과 동일한 경우 병렬 루프에서는 취소에 대해 단일 OperationCanceledException을 throw합니다. 다른 토큰에 의해 취소가 발행한 경우 루프에서는 AggregateException을 throw하고 OperationCanceledException을 InnerException으로 throw합니다.

참고 항목

개념

데이터 병렬 처리(작업 병렬 라이브러리)

PLINQ 및 TPL의 람다 식