【问题标题】:Exception handling in TPLTPL 中的异常处理
【发布时间】:2015-05-06 05:58:19
【问题描述】:

我正在使用以下代码来创建一些文件。

我观察到,有时如果发生一些异常,所有 Parallel.For 线程都会在两者之间停止。

我有几个问题。

  1. 我应该在 CreateReport 方法或其@rt 位置使用 AggregateException。

  2. 如何确保如果任何线程中出现异常,它不会停止其他并行线程。

    Try
            dtScheduledReports = objReprotHelper.GetTopImmediateReportsForExecution()

        Parallel.For(0, dtScheduledReports.Rows.Count, Sub(i)
                                                           CreateReport(dtScheduledReports.Rows(i))
                                                       End Sub)
    Catch ae As AggregateException
        For Each ex As Exception In ae.InnerExceptions
            ExceptionHandler.LogError(ex)
        Next
    End Try

Private Sub CreateReport(dtRow As DataRow, scheduleType As Integer)
        Try
              //do something
        Catch 
              throw
        End Try
    End Sub

【问题讨论】:

  • 你认为他们为什么会停下来?
  • 我维护数据库中每个报告的状态,即进度检查,如开始、结束。有些永远不会结束。
  • CreateReport 是做什么的?它可以访问数据库吗?
  • 是的,确实如此。从 DB 中获取所需信息并创建 csv 文件。

标签: vb.net multithreading task-parallel-library


【解决方案1】:

您可以使用ConcurrentQueue(Of Exception) 来启用来自多个线程的安全异常排队。这允许执行整个循环并在AggregateException 中抛出所有异常。

Private Sub DoAParalelJobAndThrowErrors

  Dim exQueue as New ConcurrentQueue(Of Exception)
  dtScheduledReports = objReprotHelper.GetTopImmediateReportsForExecution()
  // Execute the complete loop and capture all exceptions.
  Parallel.For(0, dtScheduledReports.Rows.Count, Sub(i)
                                                       Try
                                                         CreateReport(dtScheduledReports.Rows(i))
                                                       Catch ex as Exception
                                                         exQueue.Enqueue(ex)
                                                       End Try
                                                     End Sub)

  If exQueue.count > 0 throw new AggregateException(exQueue)

End Sub

Private Sub CreateReport(dtRow As DataRow, scheduleType As Integer)       
    //do something
End Sub

根据 MSDN,这种方式不会中断循环,应该处理所有行。

【讨论】:

  • 感谢您的回复,但我不应该只是在 CreateReport 中添加一个 try catch,这样它只会中断当前执行而不是整个循环。
  • 通过 catch 忽略异常是个坏主意。如果您在 CreateReport 中使用 concurrentQueue,您将添加一个丑陋的依赖项。如果从其他不平行的地方调用 CreateReport 怎么办?为什么必须了解 concurrenQueue?让 createReport 成为标准异常处理的标准动作(在这种情况下让异常在堆栈中冒泡)并将特殊异常处理放在您的特殊方法中(并行)。
猜你喜欢
  • 2012-04-14
  • 2012-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-01
  • 2016-02-07
  • 1970-01-01
相关资源
最近更新 更多