我要在运行时优化的 VB.NET Framework 4.0应用程序中有一个大型的初始化例程。由于当今大多数计算机能够一次执行多个线程,因此我想引入多线程来并行执行非依赖性,因此减少了用户初始化应用程序的总时间。
原始(单线程)实现如下所示:
Friend Module MainModule
Friend Sub Main()
LongRunningInitialization1()
LongRunningInitialization2()
LongRunningInitialization3()
LongRunningInitialization4()
LongRunningInitialization5()
LongRunningInitialization6()
LongRunningInitialization7()
End Sub
Private Sub LongRunningInitialization1()
End Sub
Private Sub LongRunningInitialization2()
End Sub
Private Sub LongRunningInitialization3()
End Sub
Private Sub LongRunningInitialization4()
End Sub
Private Sub LongRunningInitialization5()
End Sub
Private Sub LongRunningInitialization6()
End Sub
Private Sub LongRunningInitialization7()
End Sub
End Module
我的第一种方法是使用System.Threading.Thread
来并行化工作负载:
Friend Sub Main()
Dim thread1 As New Threading.Thread(AddressOf LongRunningInitialization1)
Dim thread2 As New Threading.Thread(AddressOf LongRunningInitialization2)
Dim thread3 As New Threading.Thread(AddressOf LongRunningInitialization3)
Dim thread4 As New Threading.Thread(AddressOf LongRunningInitialization4)
Dim thread5 As New Threading.Thread(AddressOf LongRunningInitialization5)
Dim thread6 As New Threading.Thread(AddressOf LongRunningInitialization6)
Dim thread7 As New Threading.Thread(AddressOf LongRunningInitialization7)
thread1.Join()
thread2.Join()
thread3.Join()
thread4.Join()
thread5.Join()
thread6.Join()
thread7.Join()
End Sub
尽管这项基本工作有效,Join()
是一个阻塞调用,并且在thread1
花费时间最长的场景中,只要thread1
完成,其他线程都是“僵尸” 。另外,由于Join()
被阻止,因此未实现的带有进度条的初始屏幕冻结。
我通过使用线程的while and the
ThreadState`属性以一种怪异的方式进行非阻塞等待而提出了另一个“解决方案”:
Friend Sub Main()
Dim thread1 As New Threading.Thread(AddressOf LongRunningInitialization1)
Dim thread2 As New Threading.Thread(AddressOf LongRunningInitialization2)
Dim thread3 As New Threading.Thread(AddressOf LongRunningInitialization3)
Dim thread4 As New Threading.Thread(AddressOf LongRunningInitialization4)
Dim thread5 As New Threading.Thread(AddressOf LongRunningInitialization5)
Dim thread6 As New Threading.Thread(AddressOf LongRunningInitialization6)
Dim thread7 As New Threading.Thread(AddressOf LongRunningInitialization7)
While thread1.ThreadState = Threading.ThreadState.Running _
OrElse thread2.ThreadState = Threading.ThreadState.Running _
OrElse thread3.ThreadState = Threading.ThreadState.Running _
OrElse thread4.ThreadState = Threading.ThreadState.Running _
OrElse thread5.ThreadState = Threading.ThreadState.Running _
OrElse thread6.ThreadState = Threading.ThreadState.Running _
OrElse thread7.ThreadState = Threading.ThreadState.Running
Application.DoEvents() ' process the Windows Forms message queue.
Threading.Thread.Sleep(1) ' non-blocking wait.
End While
thread1.Join()
thread2.Join()
thread3.Join()
thread4.Join()
thread5.Join()
thread6.Join()
thread7.Join()
End Sub
尽管此最后一个实现在此示例中有效,但是当您面对现实世界中大约有20个长时间运行的初始化任务(大多数应并行运行)时,它不可用。 while
条件的规模将是史诗般的。
是否有一种解决方案可以对所有创建的线程执行非阻塞等待? 以下伪代码之类的东西:
Friend Sub Main()
Dim threadPool As New PseudoThreadPool()
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization1))
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization2))
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization3))
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization4))
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization5))
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization6))
threadPool.Add(New Threading.Thread(AddressOf LongRunningInitialization7))
threadPool.Start()
While threadPool.AllDone = False
Application.DoEvents() ' process the Windows Forms message queue.
Threading.Thread.Sleep(1) ' non-blocking wait.
End While
threadPool.Join()
End Sub
答案 0 :(得分:1)
由于@Jimi(List(Of Task)
方法),我找到了解决方案。
Friend Sub Main()
Dim tasks As New List(Of Task)
tasks.Add(New Task(AddressOf LongRunningInitialization1))
tasks.Add(New Task(AddressOf LongRunningInitialization2))
tasks.Add(New Task(AddressOf LongRunningInitialization3))
tasks.Add(New Task(AddressOf LongRunningInitialization4))
tasks.Add(New Task(AddressOf LongRunningInitialization5))
tasks.Add(New Task(AddressOf LongRunningInitialization6))
tasks.Add(New Task(AddressOf LongRunningInitialization7))
' Start all tasks.
tasks.All(
Function(t As Task)
t.Start()
Return True
End Function
)
' Wait until all tasks has been finished.
While tasks.Any(Function(t As Task) Not (t.Status = TaskStatus.Canceled OrElse t.Status = TaskStatus.Faulted OrElse t.Status = TaskStatus.RanToCompletion))
Application.DoEvents()
Sleep(1)
End While
End Sub