方法: Parallel.For または ForEach ループを取り消す
Parallel.For および Parallel.ForEach メソッドでは、キャンセル トークンを使用した取り消し処理がサポートされます。 一般的な取り消し処理の詳細については、「キャンセル」を参照してください。 並列ループでは、ParallelOptions パラメーターのメソッドに CancellationToken を指定してから、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 をスローします。 これにより、例外がスローされると、すべてのイテレーションが直ちに実行されなくなります。 その他のいくつかのトークンによって取り消しが行われた場合、ループは InnerException
として OperationCanceledException と共に AggregateException をスローします。
関連項目
GitHub で Microsoft と共同作業する
このコンテンツのソースは GitHub にあります。そこで、issue や pull request を作成および確認することもできます。 詳細については、共同作成者ガイドを参照してください。
.NET