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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 19:13:59  来源:igfitidea点击:

How to know if a set of threads has finished

vb.netmultithreading

提问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事件。