2015-06-22 2 views
2

Я хочу знать, если различные темы закончили делать свою работу, а затем вызвать событие, у меня есть следующий код:Как знать, если набор нитей закончили

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 

Я совершенно новый в нить, я почти уверен, что это не лучший способ сделать это, может ли кто-нибудь дать мне некоторые предложения, пожалуйста?

Я использую Framework 2.0.

ответ

3

Это очень неясно мне, что вы на самом деле пытаетесь достичь, так что трудно рекомендуют наилучшую практику.

Но за то, что вы просите, выполнение thread.Join() на каждом запущенном вами потоке будет гарантировать, что вы дождитесь завершения всех потоков.

См .NET 2.0 документ: https://msdn.microsoft.com/en-us/library/95hbf2ta(v=vs.80).aspx

Ваш код будет выглядеть примерно так:

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: Создание числа потоков регулируемых

Обычно, начиная чрезмерное количество потоков для выполнения некоторых работ - не лучшая идея. Кроме того, в зависимости от того, насколько ресурсоемкий работает каждый поток, это может вызвать общее замедление вашей программы.

Как правило, вы хотите проверить, какое количество потоков даст вам правильный баланс между выполнением работы быстрее и параллельно или злоупотреблением системными ресурсами и ухудшением общей производительности.

Следующий код должен позволять вам легко настраивать количество потоков для выполнения вашей работы и находить правильный баланс для вас.

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 
+0

Посмотрите, я пытаюсь сканировать для IP-адресов, которые связаны с приложением. «xTask» выполняется в потоке, вызванном из главного окна, когда все потоки, выполненные на «xTask», завершили свою работу, я хочу поднять событие из «xTask», которое будет захватывать основное окно. – ozat

+0

Ну, до тех пор, пока 'xTask' *** не работает *** в потоке пользовательского интерфейса (в главном окне), то, хотя вышеизложенное может быть не лучшим способом сделать это, оно достаточно просто и должно конечно работа хорошо. Просто попробуй. Однако, если 'xTask' работает в потоке пользовательского интерфейса, ваше приложение может выглядеть замороженным, пока оно блокирует ожидание завершения потоков. (TBH, я даже не уверен, что выполнение вышеизложенного в потоке пользовательского интерфейса будет на самом деле проблемой, потому что 't.Join()' предполагается поддерживать пересылку сообщений во время ожидания. Опять попробуйте и посмотрите, он работает для вас!) – sstan

+0

xTask не работает в потоке пользовательского интерфейса, я пробовал использовать t.Join, и приложение становится очень медленным при выполнении потоков. – ozat

0

Ну, я думаю, вы хотели использовать BackgroundWorker здесь. По завершении обработки рабочего стола (или если он отменен) вы можете поднять RunWorkerCompleted событие.

1

Я использовал бы библиотеку задач для этого (предполагая, что вы используете .Net 4 вверх).

Добавить каждую новую задачу в список и вы можете ждать, пока все закончить в одну линию, как показано ниже:

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 
+0

К сожалению, я не сказал, что я использую Framework 2.0 – ozat

Смежные вопросы