2015-02-09 71 views
0

我正在使用下面的代码来创建一些文件。TPL中的异常处理

我观察到有时候如果一些异常发生在所有的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 
+0

你为什么认为他们停止? – 2015-02-09 11:50:05

+0

我维护数据库中每个报告的状态,即进度检查如开始,结束。有些从未达到目的。 – 2015-02-09 12:09:52

+0

CreateReport做什么?它是否可以访问数据库? – 2015-02-09 13:04:28

回答

0

可以使用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这种方式不会打破循环,所有的行都应该被处理。

+0

感谢您的答复,但不应该只是在CreateReport中添加一个try catch,并且这样它只会打破当前的执行而不是整个循环。 – 2015-02-09 14:38:49

+0

这是一个坏主意,做一个赶上忽略例外。如果您在CreateReport中使用concurrentQueue,则会添加一个丑陋的依赖项。如果CreateReport是从其他不平行的地方调用的呢?为什么必须了解concurrenQueue?让createReport成为标准异常处理的标准动作(在这种情况下,让堆栈中的异常冒泡)并在特殊方法(parallel for)中加入特殊的异常处理。 – jlvaquero 2015-02-10 06:57:00