如何在主要终止之前确保类完成的实例?

时间:2012-02-14 20:34:52

标签: windows vb.net multithreading

我有一个使用Visual Basic的MultiThreading问题和概念性问题(但它几乎适用于所有语言)。 我有一个功能:

  1. 创建一个类的5个实例,每个实例产生一个调用函数的线程
  2. 功能睡眠时间为X毫秒
  3. 打印到控制台
  4. 然后终止线程
  5. 如何确保班级的所有实例都有机会在主要切断之前完成?

    通过研究提供最相关的帮助:How do I pause main() until all other threads have died?

    这是我的代码:

    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 个答案:

答案 0 :(得分:1)

显然,您的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中编程,所以希望我写的并不完全错误。)

答案 1 :(得分:0)

我不确定我是否遗漏了某些东西(我打赌这是一个示例项目),但我无法重现这个问题。当我运行您发布的代码时,我可以看到所有车辆进入(减去都铎提到的.Join呼叫)。

但是,如果我将Thread.IsBackground设置为True然后,我会看到您的问题。为了确保ThreadProcess终止之前完成,请执行以下操作:

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.IsBackgroundhttp://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.95).aspx

的定义

此属性会告诉您Process是否会在终止前等待Thread完成。显然,在您的情况下,您希望这是False。在许多情况下,它默认为False,但有时可能会将其设置为true。