任务不会等待"WaitAll"



我遇到了一个问题,即我的任务的"WaitAll">不会等到所有任务都完成。这是一个带有子和函数的 VB 项目。许多其他示例(在 C# 中(使用 lambda,这些 lambda 不容易转换为 VB。

我已经使用示例程序进行了测试并使其工作,但是一旦我尝试与Web服务(添加async和await(进行通信,它就不再在WaitAll上等待。

这是日志文件的一个示例。您可以看到按钮单击在第 6 行和第 7 行的结束方式,即使任务仍在运行并在按钮单击完成后继续记录工作。

2018-07-05 12:18:38.1481 |  INFO | Form1.btnRun_Click | ############################ 
2018-07-05 12:18:38.1790 |  INFO | Form1.btnRun_Click | Run button clicked 
2018-07-05 12:18:38.2129 |  INFO | ProcessOneChunkOfPeopleData | Thread #1 contains 2 people 
2018-07-05 12:18:38.2129 |  INFO | ProcessOneChunkOfPeopleData | Thread #2 contains 2 people 
2018-07-05 12:18:38.2129 |  INFO | ProcessOneChunkOfPeopleData | Thread #3 contains 2 people 
2018-07-05 12:18:38.2980 |  INFO | Form1.btnRun_Click | Run button code has completed 
2018-07-05 12:18:38.2980 |  INFO | Form1.btnRun_Click | ############################ 
2018-07-05 12:18:38.3788 |  INFO | ProcessOneChunkOfPeopleData | Thread 1. Finished processing person Peter (1 of 2) 
2018-07-05 12:18:38.3788 |  INFO | ProcessOneChunkOfPeopleData | Thread 3. Finished processing person Dave (1 of 2) 
2018-07-05 12:18:38.3947 |  INFO | ProcessOneChunkOfPeopleData | Thread 2. Finished processing person Chantal (1 of 2) 
2018-07-05 12:18:38.4665 |  INFO | ProcessOneChunkOfPeopleData | Thread 3. Finished processing person Helen (2 of 2) 
2018-07-05 12:18:38.4695 |  INFO | ProcessOneChunkOfPeopleData | Thread #3 has finished processing all people 
2018-07-05 12:18:38.4948 |  INFO | ProcessOneChunkOfPeopleData | Thread 2. Finished processing person Tammy (2 of 2) 
2018-07-05 12:18:38.5018 |  INFO | ProcessOneChunkOfPeopleData | Thread #2 has finished processing all people 
2018-07-05 12:18:38.4948 |  INFO | ProcessOneChunkOfPeopleData | Thread 1. Finished processing person Jeff (2 of 2) 
2018-07-05 12:18:38.5157 |  INFO | ProcessOneChunkOfPeopleData | Thread #1 has finished processing all people 

这是我一直在测试的代码。你能帮忙解释为什么WaitAll不等待吗?

Imports System.Net.Http
Imports NLog
Public Class Form1
Private m_Logger As Logger = LogManager.GetCurrentClassLogger
Private Sub btnRun_Click(sender As Object, e As EventArgs) Handles btnRun.Click
m_Logger.Info("############################")
m_Logger.Info("Run button clicked")
'Create a bunch of people
Dim Peter As New Person(1, "Peter")
Dim Jeff As New Person(2, "Jeff")
Dim Chantal As New Person(3, "Chantal")
Dim Tammy As New Person(4, "Tammy")
Dim Dave As New Person(5, "Dave")
Dim Helen As New Person(6, "Helen")
'Load people into groups
Dim Group1 As New List(Of Person)
Group1.Add(Peter)
Group1.Add(Jeff)
Dim Group2 As New List(Of Person)
Group2.Add(Chantal)
Group2.Add(Tammy)
Dim Group3 As New List(Of Person)
Group3.Add(Dave)
Group3.Add(Helen)
'Create a list of lists. Each list will be processed as a separate task
Dim MySplitList As New List(Of List(Of Person))
MySplitList.Add(Group1)
MySplitList.Add(Group2)
MySplitList.Add(Group3)
'Create an array of 3 tasks
Dim myTasks(2) As Task
'Load the task array with what work it needs to do
Dim iThreadNumber As Integer = 1
For Each OneList As List(Of Person) In MySplitList
Dim iNEW As Integer = iThreadNumber
myTasks(iNEW - 1) = System.Threading.Tasks.Task.Run(Sub() ProcessOneChunkOfPeopleData(OneList, iNEW))
iThreadNumber += 1
Next OneList
'Wait for all tasks to complete.
Task.WaitAll(myTasks)
m_Logger.Info("Run button code has completed")
m_Logger.Info("############################")
MessageBox.Show(Me, "Process complete", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Private Async Sub ProcessOneChunkOfPeopleData(ByVal arPeople As List(Of Person), ByVal iSectionNumber As Integer)
Try
m_Logger.Info(String.Format("Thread #{0} contains {1} people", iSectionNumber, arPeople.Count))
Dim iCounter As Integer = 1
For Each xOnePerson As Person In arPeople
'Simulate a call to a web service
Dim bWorkedOkay1 As Boolean = Await FakeApiCall()
m_Logger.Info(String.Format("Thread {0}. Finished processing person {1} ({2} of {3})", iSectionNumber, xOnePerson.Name, iCounter, arPeople.Count))
iCounter += 1
Next xOnePerson
m_Logger.Info(String.Format("Thread #{0} has finished processing all people", iSectionNumber))
Catch Exp As Exception
m_Logger.Error(Exp.Message)
End Try
End Sub
Public Async Function FakeApiCall() As Task(Of Boolean)
Dim http As New HttpClient
'This is the API which is causing the task WaitAll to not wait
Dim xResponse As HttpResponseMessage = Await http.GetAsync("https://jsonplaceholder.typicode.com/posts/1")
Dim sResult As String = Await xResponse.Content.ReadAsStringAsync()
Return True
End Function
End Class
Public Class Person
Public Property Name As String = ""
Public Property ID As Integer = 0
Public Sub New()
'
End Sub
Public Sub New(ByVal iID As Integer, ByVal sName As String)
Me.ID = iID
Me.Name = sName
End Sub
End Class

我无法解释为什么当您将 API 调用替换为睡眠时代码有效。我可以将其作为修复代码并使其等待 WaitAll 完成的解决方案。

以下是为了使项目正常工作而需要做的三个更改。所做的更改是为了使 Sub 成为一个函数 - 所以它现在被迫返回一些东西。

btnRun_Click,改变

myTasks(iNEW - 1) = System.Threading.Tasks.Task.Run(Sub() ProcessOneChunkOfPeopleData(OneList, iNEW))

要成为

myTasks(iNEW - 1) = System.Threading.Tasks.Task.Run(Function() ProcessOneChunkOfPeopleData(OneList, iNEW))

从此更改功能ProcessOneChunkOfPeopleData

Private Async Sub ProcessOneChunkOfPeopleData(ByVal arPeople As List(Of Person), ByVal iSectionNumber As Integer)

对此

Private Async Function ProcessOneChunkOfPeopleData(ByVal arPeople As List(Of Person), ByVal iSectionNumber As Integer) As Task(Of Boolean)

将其添加到ProcessOneChunkOfPeopleData的最后一行

Return True

相关内容

  • 没有找到相关文章