Как гарантировать, что экземпляры класса заканчивают работу перед завершением main? - PullRequest
0 голосов
/ 15 февраля 2012

У меня проблема с многопоточностью и концептуальный вопрос с использованием Visual Basic (но это относится почти ко всем языкам).У меня есть функция, которая:

  1. создает 5 экземпляров класса, каждый из которых порождает поток, который вызывает функцию
  2. Функция спит в течение X миллисекунд
  3. выводит на консоль
  4. , затем завершает поток

Как я могу гарантировать, что все экземпляры класса получат возможность завершить работу до того, как main отключит их ??

Самая важная помощь в исследованиях: Как приостановить 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 ]

1 голос
/ 15 февраля 2012

Очевидно, ваш конструктор 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, так что, надеюсь, то, что я написал, не совсем неверно.)

0 голосов
/ 15 февраля 2012

Я не уверен, что что-то упустил (держу пари, это пример проекта), но не могу воспроизвести проблему.Я вижу все машины, которые приходят, когда я запускаю код, который вы опубликовали (за исключением вызова .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.

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