等待使用可等待的方法迭代数据表

Await iterating a datatable with awaitable methods

我有以下异步方法,它等待每行 babsis 上的单独方法。我终其一生都无法弄清楚如何将其提升到一个新的水平,并等待处理整个数据表(即让所有行一起开始,而不是一次一个)。任何帮助将不胜感激。

    Public Async Function GetLabResultPanelPackByPRN_Async(ByVal ClientID As Integer, ByVal PRN As Integer, ByVal SamplePointID As Integer, ByVal StartDate As DateTime, ByVal EndDate As DateTime, ByVal InequalityMode As InequalityModes) As Task(Of List(Of LabResultPanelPack))
    Dim LRPPs As New List(Of LabResultPanelPack)
    Dim ta As New eniCIP_DataTableAdapters.proc_WebPortal_ResultsByPRNTableAdapter
    Dim dt As New eniCIP_Data.proc_WebPortal_ResultsByPRNDataTable
    ta.Fill(dt, PRN)
    For Each row As eniCIP_Data.proc_WebPortal_ResultsByPRNRow In dt
        Dim LRPP As New LabResultPanelPack
        LRPP.LabResult = GetLabResultByPRNFromRow(row, InequalityMode)

        Dim ResultsByDetAndSPTask As Task(Of List(Of LabResultExtended)) = GetResultsByDetAndSP_Async(ClientID, SamplePointID, row.lDetID, StartDate, EndDate, InequalityMode)
        Dim ResultsBySampleTypeAndDetTask As Task(Of List(Of LabResultExtended)) = GetResultsBySampleTypeAndDet_Async(ClientID, row.lSampleTypeID, row.lDetID, StartDate, EndDate, InequalityMode)
        Dim ResultsBySampleTypeGroupAndDetTask As Task(Of List(Of LabResultExtended)) = GetResultsBySampleTypeGroupAndDet_Async(ClientID, row.lSampleTypeGroupID, row.lDetID, StartDate, EndDate, InequalityMode)

        LRPP.HistoricResultsByDetAndSP = Await ResultsByDetAndSPTask
        LRPP.HistoricResultsByDetAndSampleType = Await ResultsBySampleTypeAndDetTask
        LRPP.HistoricResultsByDetAndSampleTypeGroup = Await ResultsBySampleTypeGroupAndDetTask

        LRPPs.Add(LRPP)
    Next

    Return LRPPs
End Function

这种情况下的解决方案是简单地添加一个函数,事情很快就会解决。

如果您创建一个新函数来处理 one 行,如下所示:

Private Async Function ProcessRow(row As YourRowType, ...) As Task(Of LabResultPanelPack)
  Dim LRPP As New LabResultPanelPack
  LRPP.LabResult = GetLabResultByPRNFromRow(row, InequalityMode)

  'Add your tasks for processing the row further
  Return LRPP
End Function

现在你的主循环看起来像这样:

For Each row As eniCIP_Data.proc_WebPortal_ResultsByPRNRow In dt
  Dim LRPP = Await ProcessRow(row, ...)
  LRPPs.Add(LRPP)
Next

此时您可以将 LRPPs 列表更改为

Dim LRPPTasks As New List(Of Task(Of LabResultPanelPack))

并将循环更改为

For Each row As eniCIP_Data.proc_WebPortal_ResultsByPRNRow In dt
  Dim LRPPTask = ProcessRow(row, ...)
  LRPPTasks.Add(LRPPTask)
Next

这样您就可以避免等待每一行,并在到达 ProcessRow 函数中的第一个 await 后立即继续处理这些行。

最后您需要做的就是将 return 更改为

Return Await Task.WhenAll(LRPPTasks)

大功告成。

作为一个小补充:按照我的建议重写代码后,您最终会得到 Function 中唯一的 Await。这意味着您可以从函数中删除 Async 标志,并从 Return 中删除 Await。这样你的开销就会少一些。