如何:取消 Parallel.For 或 ForEach 迴圈
Parallel.For 和 Parallel.ForEach 方法可透過使用取消權杖來支援取消作業。 如需取消的詳細資訊,請參閱取消。 在平行迴圈中,將 CancellationToken 提供給 ParallelOptions 參數中的方法,然後將平行呼叫包含在 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。 這會在擲回例外狀況時,立即停止執行所有反覆項目。 如果是其他權杖導致取消,迴圈將會擲回 AggregateException,而其中的 OperationCanceledException 是 InnerException
。