다음을 통해 공유


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

Parallel.ForParallel.ForEach 메서드는 취소 토큰을 사용하는 방법으로 취소 기능을 지원합니다. 일반적으로 취소에 대한 자세한 내용은 취소를 참조하세요. 병렬 루프에서는 CancellationTokenParallelOptions 매개 변수의 메서드에 제공하고 try-catch 블록으로 병렬 호출을 묶습니다.

예시

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

namespace CancelParallelLoops
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;

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

            // Use ParallelOptions instance to store the CancellationToken
            ParallelOptions options = new()
            {
                CancellationToken = cts.Token,
                MaxDegreeOfParallelism = 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 is 'c')
                    cts.Cancel();
                Console.WriteLine("press any key to exit");
            });

            try
            {
                Parallel.ForEach(nums, options, (num) =>
                {
                    double d = Math.Sqrt(num);
                    Console.WriteLine("{0} on {1}", d, Environment.CurrentManagedThreadId);
                });
            }
            catch (OperationCanceledException e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                cts.Dispose();
            }

            Console.ReadKey();
        }
    }
}
' 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)
                                       End Sub)

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

        Console.ReadKey()

    End Sub
End Module

취소 신호를 보내는 토큰이 ParallelOptions 인스턴스에 지정된 것과 동일한 토큰이면 병렬 루프에서 취소에 대한 단일 OperationCanceledException를 throw합니다. 그러면 예외가 throw되면 모든 반복 실행이 즉시 중지됩니다. 다른 토큰으로 인해 취소가 throw되면 루프는 OperationCanceledExceptionInnerException으로 사용하여 AggregateException을 throw합니다.

참고 항목