Vorgehensweise: Abbrechen einer Parallel.For-Schleife oder einer ForEach-Schleife
Die Parallel.For- und Parallel.ForEach-Methode unterstützen den Abbruch durch die Verwendung von Abbruchtoken. Weitere Informationen über Abbrüche im Allgemeinen finden Sie unter Abbruch in verwalteten Threads. Übergeben Sie in einer parallelen Schleife das CancellationToken mit dem ParallelOptions-Parameter an die Methode, und schließen Sie den parallelen Aufruf in einen Try-Catch-Block ein.
Beispiel
Im folgenden Beispiel wird der Abbruch des Aufrufs einer Parallel.ForEach-Methode veranschaulicht. Sie können den gleichen Ansatz auf einen Parallel.For-Aufruf anwenden.
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
Wenn das Token, das den Abbruch signalisiert, mit dem in der ParallelOptions-Instanz angegebenen identisch ist, löst die parallele Schleife beim Abbruch eine einzelne OperationCanceledException aus. Dadurch wird die Ausführung aller Iterationen sofort beendet, wenn die Ausnahme ausgelöst wird. Wenn ein anderes Token den Abbruch verursacht, löst die Schleife eine AggregateException mit einer OperationCanceledException als InnerException
aus.