找出一个线程是否已经启动?

Lan*_*ens 3 c# multithreading .net-4.0 dispatcher polling

我有以下代码:

var x = new Thread(new ThreadStart(Delegate));
x.Start();
Run Code Online (Sandbox Code Playgroud)

这将创建一个新线程并启动它.

如何在没有do while循环的情况下检测到线程X已经开始执行?

usr*_*ΛΩΝ 6

使用信号量互斥锁或自动/手动重置事件.

//Initialize semaphore, set it to BLOCK
ManualResetEvent sema = new ManualResetEvent(false);

void Main()
{
    var x = new Thread(Delegate);
    //Request the system to start the thread.
    //This doesn't mean the CPU will immediately run Delegate method
    //but eventually it will do
    x.Start(sema);

    //Stop here and don't do anything on this thread until the semaphore is FREE
    sema.WaitOne();

    [continued main thread]
}

void Delegate(Semaphore sema){
    //Unblock the semaphore
    sema.Set(1);
    [your code here]
}
Run Code Online (Sandbox Code Playgroud)

深刻的解释

多线程背后的原则之一是非确定性.如果您没有使用正确的技术,如上所述,您无法预测在多个线程中完成的操作的行为如果您有这样的方法

void Main()
{
    A();
    B();
    C();
}
Run Code Online (Sandbox Code Playgroud)

然后你确定B从未在A之前或之后执行.这同样不适用于多线程.

void Main()
{
    new Thread(A).Start();
    new Thread(B).Start();
    new Thread(C).Start();

    D();
}
Run Code Online (Sandbox Code Playgroud)

您确定运行B started的线程在运行A的线程之后,但在多线程中这意味着不同的东西.从MSDN和每本编程书开始,启动一个线程仅仅意味着要求操作系统在内核中分配适当的工具来支持多线程.如果这样做(线程已正确创建并计划执行),则该方法将返回而不会出现错误.可能会发生操作系统以任何顺序运行三个线程,具体取决于几个因素.

所以,如果你对它们进行调试到控制台(认为每做了Console.WriteLine("Hello, I'm thread A/B/C"),你可以在不同的执行任何命令:A,B,C; A,C,B; B,C,A等等.

所以你现在想要确保,但确实,确实,在运行D之前,特定或每个线程都已经真正启动.事实上,在许多单核CPU情况下,操作系统应该D在每个线程之前运行方法.这也是不可预测的!所以在无法预测何时A,B和C运行后,你无法预测D何时运行!!

显式同步是强制暂停代码执行并等待事件发生的技术.信号量释放所描述的事件取决于上下文,所以在你的情况下,你只是告诉主线程"等待代表已经开始,然后做你想做的任何事情":)

替代的,低效的方法

使用信号量只是使用无限循环执行以下操作的有效方法

volatile bool threadStarted = false;

void Main()
{
    var x = new Thread(Delegate);
    x.Start();

    while (!threadStarted);
    [continued main thread]
}

void Delegate(Semaphore sema){
    threadStarted = true;
    [your code here]
}
Run Code Online (Sandbox Code Playgroud)

使用信号量不会简单地浪费CPU来连续检查某个标志是低还是高