添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Parallel.For Parallel.ForEach 重载没有任何用于处理可能引发的异常的特殊机制。 在这一方面,它们类似于常规 for foreach 循环(在 Visual Basic 中为 For For Each );未处理的异常会导致循环在当前运行的迭代完成后立即终止。

向并行循环添加自己的异常处理逻辑时,将处理类似于在多个线程上同时引发相似异常的情况,以及一个线程上引发异常导致另一个线程上引发另一个异常的情况。 你可以通过将循环中的所有异常包装到一个 System.AggregateException 中处理这两种情况。 下面的示例演示了一种可能的方法。

某些情况下,当启用“仅我的代码”后,Visual Studio 会在引发异常的行中断运行并显示一条错误消息,该消息显示“用户代码未处理异常”。该错误是良性错误。 可以按 F5 继续运行,并请参阅下面示例中所示的异常处理行为。 为了阻止 Visual Studio 在第一个错误出现时中断,只需依次转到“工具”、“选项”、“调试”、“常规”下,取消选中“仅我的代码”复选框即可。

在此示例中,所有异常都被捕获,并包装到引发的 System.AggregateException 中。 调用方可以决定要处理哪些异常。

public static partial class Program
    public static void ExceptionTwo()
        // Create some random data to process in parallel.
        // There is a good probability this data will cause some exceptions to be thrown.
        byte[] data = new byte[5_000];
        Random r = Random.Shared;
        r.NextBytes(data);
            ProcessDataInParallel(data);
        catch (AggregateException ae)
            var ignoredExceptions = new List<Exception>();
            // This is where you can choose which exceptions to handle.
            foreach (var ex in ae.Flatten().InnerExceptions)
                if (ex is ArgumentException) Console.WriteLine(ex.Message);
                else ignoredExceptions.Add(ex);
            if (ignoredExceptions.Count > 0)
                throw new AggregateException(ignoredExceptions);
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    private static void ProcessDataInParallel(byte[] data)
        // Use ConcurrentQueue to enable safe enqueueing from multiple threads.
        var exceptions = new ConcurrentQueue<Exception>();
        // Execute the complete loop and capture all exceptions.
        Parallel.ForEach(data, d =>
                // Cause a few exceptions, but not too many.
                if (d < 3) throw new ArgumentException($"Value is {d}. Value must be greater than or equal to 3.");
                else Console.Write(d + " ");
            // Store the exception and continue with the loop.
            catch (Exception e)
                exceptions.Enqueue(e);
        Console.WriteLine();
        // Throw the exceptions here after the loop completes.
        if (!exceptions.IsEmpty)
            throw new AggregateException(exceptions);
' How to: Handle Exceptions in Parallel Loops
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Threading.Tasks
Module ExceptionsInLoops
    Sub Main()
        ' Create some random data to process in parallel.
        ' There is a good probability this data will cause some exceptions to be thrown.
        Dim data(1000) As Byte
        Dim r As New Random()
        r.NextBytes(data)
            ProcessDataInParallel(data)
        Catch ae As AggregateException
            Dim ignoredExceptions As New List(Of Exception)
            ' This is where you can choose which exceptions to handle.
            For Each ex As Exception In ae.Flatten().InnerExceptions
                If (TypeOf (ex) Is ArgumentException) Then
                    Console.WriteLine(ex.Message)
                    ignoredExceptions.Add(ex)
                End If
            If ignoredExceptions.Count > 0 Then
                Throw New AggregateException(ignoredExceptions)
            End If
        End Try
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub
    Sub ProcessDataInParallel(ByVal data As Byte())
        ' Use ConcurrentQueue to enable safe enqueueing from multiple threads.
        Dim exceptions As New ConcurrentQueue(Of Exception)
        ' Execute the complete loop and capture all exceptions.
        Parallel.ForEach(Of Byte)(data, Sub(d)
                                                ' Cause a few exceptions, but not too many.
                                                If d < 3 Then
                                                    Throw New ArgumentException($"Value is {d}. Value must be greater than or equal to 3")
                                                    Console.Write(d & " ")
                                                End If
                                            Catch ex As Exception
                                                ' Store the exception and continue with the loop. 
                                                exceptions.Enqueue(ex)
                                            End Try
                                        End Sub)
        Console.WriteLine()
        ' Throw the exceptions here after the loop completes.
        If exceptions.Count > 0 Then
            Throw New AggregateException(exceptions)
        End If
    End Sub
End Module
  • PLINQ 和 TPL 中的 Lambda 表达式
  •