Как обеспечить, чтобы экземпляры класса заканчивались до завершения основного?
У меня есть проблема с многопоточностью и концептуальный вопрос с использованием Visual Basic (но это относится почти ко всем языкам). У меня есть функция, которая:
- создает 5 экземпляров класса, каждый из которых порождает поток, вызывающий функцию
- Функция спит в течение X миллисекунд
- выводит на консоль
- затем завершает поток
Как я могу гарантировать, что все экземпляры класса получат шанс закончить до того, как главный обрежет их?
Наиболее актуальная помощь в исследованиях: как сделать паузу main(), пока все остальные потоки не прекратятся?
Вот мой код:
Imports System
Imports System.Threading
Imports System.Collections.Generic
Module Module1
Private raceTrack As New List(Of RaceCar)
Sub Main()
CreateRace()
'Main() would quit when the 5 car objects are created =[
'How do I make sure Main will not exit until all racecars are done?
End Sub
Sub CreateRace()
For index As Integer = 1 to 5
raceTrack.Add(new RaceCar(index))
Next
End Sub
Public Class RaceCar
Private testThread as Thread = New Thread(AddressOf StartEngine)
Private carId as Integer
Public Sub New(ByVal carNumber as Integer)
me.carId = carNumber
Me.TestThread.Start()
Me.TestThread.Join()
End Sub
Public Sub StartEngine()
Console.WriteLine(String.Format("Car#{0} is going!", Me.carId))
Thread.Sleep(100*Me.carId)
Console.WriteLine(String.Format("Car#{0} is DONE!", Me.carId))
End Sub
End Class
End Module
2 ответа
Видимо твой RaceCar
конструктор возвращает только когда законченный порожденный поток, так как вы вызываете Join
,
Public Sub New(ByVal carNumber as Integer)
me.carId = carNumber
Me.TestThread.Start()
Me.TestThread.Join()
End Sub
Я не знаю, является ли это намеренным (скорее всего, нет, потому что вы создаете свой RaceCar
экземпляры в цикле, так что у вас нет параллелизма, поскольку следующий экземпляр не может быть создан до тех пор, пока не вернется предыдущий вызов конструктора), но ваш основной поток не может завершиться, пока не завершатся все дочерние потоки.
Я предлагаю следующую реструктуризацию:
Удалить Join
от конструктора и добавьте новый метод в ваш RaceCar
учебный класс:
Public Sub JoinThread()
Me.TestThread.Join()
End Sub
Теперь цикл создания объекта не будет блокироваться. Добавьте еще один цикл потом:
Sub CreateRace()
For index As Integer = 1 to 5
raceTrack.Add(new RaceCar(index))
Next
// other work maybe?
For Each car As RaceCar In raceTrack
car.JoinThread()
Next
End Sub
Теперь ваши потоки будут запускаться в первом цикле, работать параллельно и, в конце концов, остановятся на новом "барьерном цикле".
Обратите внимание, что основной поток все еще может выполнять другие задачи между двумя циклами.
(Отказ от ответственности: я никогда не программировал на vb.net, так что, надеюсь, то, что я написал, не совсем неправильно.)
Я не уверен, что что-то упустил (держу пари, это пример проекта), но не могу воспроизвести проблему. Я вижу все машины, которые приходят, когда я запускаю код, который вы опубликовали (за исключением вызова.Join, как упомянуто Тудором).
Но если я установлю Thread.IsBackground
в True
тогда я вижу твою проблему. Чтобы убедиться, что ваш Thread
s заканчивают перед Process
завершается, сделайте это:
Public Sub New(ByVal carNumber As Integer)
Me.carId = carNumber
Me.testThread.IsBackground = False ' <--This will cause threads to be 'Foreground'
Me.testThread.Start()
End Sub
Взгляните на определение Thread.IsBackground
: http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.95).aspx
Это свойство сообщает вам, Process
будет ждать Thread
закончить, прежде чем прекратить. Очевидно, в вашем случае, вы хотите, чтобы это было False
, По умолчанию False
во многих случаях, но могут быть случаи, когда для него установлено значение true.