次の方法で共有


方法: Parallel.For または ForEach ループを取り消す

Parallel.For メソッドおよび Parallel.ForEach メソッドは、キャンセル トークンを使用したキャンセルをサポートしています。 一般的なキャンセルの詳細については、「キャンセル」を参照してください。 並列ループでは、CancellationTokenParallelOptions パラメーターのメソッドに指定し、並列呼び出しを 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 をスローします。 その他のトークンによってキャンセルが発生した場合、ループは OperationCanceledException と共に AggregateException を InnerException としてスローします。

参照

概念

データの並列化 (タスク並列ライブラリ)

PLINQ および TPL のラムダ式