vb.net 如何知道一组线程是否已完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30986306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to know if a set of threads has finished
提问by ozat
I want to know if various threads has finished doing their work and then raise an event, I have the following code:
我想知道各个线程是否完成了他们的工作然后引发了一个事件,我有以下代码:
Private Sub xTask(ByVal Value As String)
Try
Dim th As Thread
For i As Integer = 1 To 254
th = New Thread(Sub() YTask(Value + i))
th.IsBackground = True
th.Start()
Next
'If all threads have finished working, raise an event
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
I'm completely new at threading, I'm almost sure that this isn't the best way to do it, could anyone give me some suggestions please?
我是线程的新手,我几乎可以肯定这不是最好的方法,有人能给我一些建议吗?
I'm using Framework 2.0.
我正在使用框架 2.0。
采纳答案by sstan
It's very unclear to me what you are really trying to accomplish, so it's hard to recommend a best practice.
我不清楚你真正想要完成什么,所以很难推荐最佳实践。
But for what you are asking, doing a thread.Join()on every thread that you start will ensure that you wait for all threads to complete.
但是对于您所要求的,在thread.Join()您启动的每个线程上执行 a将确保您等待所有线程完成。
See .NET 2.0 doc: https://msdn.microsoft.com/en-us/library/95hbf2ta(v=vs.80).aspx
请参阅 .NET 2.0 文档:https: //msdn.microsoft.com/en-us/library/95hbf2ta(v=vs.80) .aspx
Your code would then look something like this:
您的代码将如下所示:
Private Sub xTask(ByVal value As String)
Dim threadList As List(Of Thread) = New List(Of Thread)
For i As Integer = 1 To 254
Dim t = New Thread(Sub() YTask(value))
t.IsBackground = True ' not sure why you want this if you are going to wait for the thread to finish anyways.
t.Start()
threadList.Add(t)
Next
' wait for all threads to finish.
' The loop will only exit once all threads have completed their work.
For Each t In threadList
t.Join()
Next
' Raise event now that all the threads have completed.
End Sub
EDIT: Making the number of threads adjustable
编辑:使线程数可调
Usually, starting an excessive amount of threads to perform some work is not the best idea. Also depending on how resource intensive each of the thread's work is, it can cause an overall slowdown of your program.
通常,启动过多的线程来执行某些工作并不是最好的主意。此外,根据每个线程工作的资源密集程度,它可能会导致程序整体变慢。
Usually, you want to test which number of threads will give you the proper balance between accomplishing the work faster and in parallel vs. abusing system resources and causing overall performance degradation.
通常,您想测试多少线程将使您在更快地并行完成工作与滥用系统资源和导致整体性能下降之间取得适当的平衡。
The following code should allow you to easily tune the number of threads to perform your work, and find the right balance for you.
下面的代码应该允许您轻松调整线程的数量来执行您的工作,并为您找到合适的平衡点。
Sub Main()
xTask("192.168.10.")
End Sub
Private Sub xTask(ByVal value As String)
Dim ipAddressesToScan As Queue(Of String) = New Queue(Of String)
SyncLock ipAddressesToScan ' I'm not 100% sure this locking is needed here, but I would do it to be safe, and it doesn't hurt.
For i As Integer = 1 To 254
ipAddressesToScan.Enqueue(value & i)
Next
End SyncLock
Dim threadList As List(Of Thread) = New List(Of Thread)
For i As Integer = 1 To 10 ' <-- change this to whatever number of threads seems to work best for you.
Dim t = New Thread(Sub() YTask(ipAddressesToScan))
't.IsBackground = True ' don't think you need this TBH.
t.Start()
threadList.Add(t)
Next
' Wait for all threads to finish processing the queue.
For Each t In threadList
t.Join()
Next
' Raise event HERE to signal that all the threads have completed.
Console.WriteLine("All threads have finished their work")
End Sub
Private Sub YTask(ByVal ipAddressesToScan As Queue(Of String))
Dim ipAddress As String
Do
SyncLock ipAddressesToScan
If ipAddressesToScan.Count = 0 Then
ipAddress = Nothing
Else
ipAddress = ipAddressesToScan.Dequeue
End If
End SyncLock
If Not String.IsNullOrEmpty(ipAddress) Then
' Perform your scan here...
Console.WriteLine(Thread.CurrentThread.ManagedThreadId & " is scanning IP Address " & ipAddress)
End If
Loop While Not String.IsNullOrEmpty(ipAddress)
End Sub
回答by James Harcourt
I would use the Task library for this (assuming you are using .Net 4 upwards).
我会为此使用 Task 库(假设您使用的是 .Net 4 以上)。
Add each new task to a list and you can wait for all to finish in one line as shown below:
将每个新任务添加到列表中,您可以在一行中等待所有任务完成,如下所示:
Private Sub xTask(ByVal Value As String)
Try
Dim task As Task
Dim tasks As New List(Of Task)
For i As Integer = 1 To 254
task = New Task(Sub() YTask(Value))
tasks.Add(task)
task.Start()
Next
' wait up to 5 seconds for all tasks to complete
Task.WaitAll(tasks.ToArray, 5000)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
回答by Rahul
Well, I think you meant to use BackgroundWorkerhere. On completion of the background worker processing (or if it's cancelled) you can raise RunWorkerCompletedevent.
好吧,我想你打算在BackgroundWorker这里使用。在后台工作进程完成后(或者如果它被取消),您可以引发RunWorkerCompleted事件。

