我试图使用线程和ThreadPool加速代码,但是我无法等到所有线程执行后再退出sub。
我尝试了很多方法,下面的代码是我的最后一次尝试。 它等待但直到所有线程都结束。
我哪里错了?
Public ThrStarted As Integer
Sub Main
ThreadPool.SetMaxThreads(10, 10)
Dim ArrVal() As Object
For LitiThr% = 0 To Liti.getUpperbound(1)
Erase ArrVal
ArrVal = {Liti(3, LitiThr), Liti(0, LitiThr), CInt(Liti(4, LitiThr)), CInt(Liti(1, CicloLitiThr)), CInt(Liti(2, LitiThr))}
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf mThread), ArrVal)
Next CicloLitiThr
Dim workerThreads%
Dim completionPortThreads%
Do
ThreadPool.GetAvailableThreads(workerThreads, completionPortThreads)
Me.lblTotal.Text = workerThreads & " / " & completionPortThreads
Me.TBox_LitiUpd.Text = LitiUpd.ToString
Application.DoEvents()
'With This I want to wait until all threads executed but it doesn't seems to work
Loop Until (ThrStarted - 1) = Liti.getUpperbound(1) And workerThreads = 0
End Sub
Sub mThread(ByVal ArrVal() As Object)
ThrStarted += 1
'Some code
End Sub
我已经阅读了很多问题/答案,我发现很多提示都是为了切换到" Parallel.ForEach"但是我无法更改我的代码(这是我第一次尝试使用线程)。
更新:
根据您的建议(激励+1)我改变了我的代码如下,但现在我无法在UI上显示线程的状态。
我害怕我无法使用"等待"因为我使用VS2010快递和(在MSDN上)我读过: " Async和Await关键字是在Visual Studio 2012中引入的。"
那么,我该怎么办?
Dim mDaPass(Liti.getUpperbound(1)) As Object
Dim mDaIns() As Object
For LitiThr% = 0 To Liti.getUpperbound(1)
Erase mDaIns
mDaIns = {Liti(3, LitiThr), Liti(0, LitiThr), CInt(Liti(4, LitiThr)), CInt(Liti(1, LitiThr)), CInt(Liti(2, LitiThr))}
mDaPass(LitiThr%) = mDaIns
Next LitiThr
Parallel.ForEach(mDaPass, AddressOf mThread)
Task.WaitAll()
答案 0 :(得分:2)
线程池是一个全局资源。不要乱用它的配置。您无法可靠地查询可用线程数等,因为池是为整个进程共享的。你需要扔掉它。
熟悉现代.NET线程API。所有这些都已经过时了。
我无法很好地阅读VB代码。可能你想开始一些任务(例如List<Task>
),然后使用Task.WaitAll
等待它们全部完成。
请勿使用DoEvents
。使用标准技术之一来保持UI线程不被阻止。例如await
。