并行每个进入死锁

时间:2016-07-18 19:38:28

标签: asp.net vb.net parallel-processing task-parallel-library

我正在尝试使用并行每个循环遍历超过100 000行的数据表。一切都可以正常工作,大约25000次迭代。我没有得到任何错误,我看到应用程序仍在工作,但它有点阻止,没有任何反应。我试图将循环封装在factory.startnew中,并且无缘无故地在大约5000次迭代中获得随机中止预测。

Dim lstExceptions As New ConcurrentQueue(Of Exception)
Dim options As New ParallelOptions
options.MaxDegreeOfParallelism = 3

Parallel.ForEach(ReservationReportDS.Tables(0).AsEnumerable(), options,
    Sub(row)
        Try
            Dim tmpRow As DataRow = CType(row, DataRow)
            Dim ReservationID As Integer = tmpRow.Field(Of Integer?)("autNoReservation")
            Dim customerID As Integer = tmpRow.Field(Of Integer?)("CustomerID")
            Dim VehiculeID As Integer = tmpRow.Field(Of Integer?)("autNoVehicule")

            Dim bill As New BillingPath()
            bill.Calculate_Billing(ReservationID, customerID, VehiculeID)

        Catch err As Exception
            lstExceptions.Enqueue(err)
        End Try
    End Sub
)

If (lstExceptions.Count > 0) Then
    Throw New AggregateException(lstExceptions)
End If

Catch errAgg As AggregateException
    For Each ex As Exception In errAgg.InnerExceptions
        Log(Log_Billing_UI, "", System.Reflection.MethodBase.GetCurrentMethod().Name & GetExceptionInfo(ex))
    Next
Catch ex As Exception
    Log(Log_Billing_UI, "", System.Reflection.MethodBase.GetCurrentMethod().Name & GetExceptionInfo(ex))
End Try

2 个答案:

答案 0 :(得分:2)

由于您有这么多的记录,我建议您考虑以下概念:

  1. 首先将所有记录读入ConcurrentQueue(Of SomeBillingInfoClass)集合 - 它将允许您不保持与打开的数据库的连接,使用从数据库读取的数据进行线程安全的休息操作。
  2. 使用Billing calc代码创建任务列表。这将允许您并行运行任务并轻松地从#1传递ConcurrentQueue变量。
  3. 保持任务在循环中运行,同时ConcurrentQueue中至少有一个元素仍然存在。
  4. 如果您可以将结算计算结果汇总到其他类 - 您可以使用其他线程安全的ConcurrentQueue(Of BillingCalcResultInfoClass)集合来完成。
  5. 计算完所有账单后 - 在单线程和单个长事务中写入数据库 - 这可能比向粒子写入粒度更快。
  6. 关于您的代码的一些注意事项 - 我认为您可能不需要手动抛出AggregateException - .Net环境将自动为您执行此操作。你只需要在.ContinueWith()方法中捕获它(对不起,大多数时候我是c#开发人员并使用c#表示法。)

    我使用类似的方法来处理数百万条记录,并且工作正常。通常我使用3-5个任务。但你总能研究你可能有多少任务。

    使用ConcurrentQueue或类似的线程安全集合可以让您更轻松地保护代码线程安全。

    如果您有任何疑问,请与我们联系。

答案 1 :(得分:0)

谢谢大家的回答,特别是Anton Norko。我终于找到了问题,它就在我身边。在某些情况下,Calculate_Billing陷入无限循环。由于我同时使用了3个线程,所以它们一个接一个地被卡住了。