C# 无法加入主线程

C# Cannot join main thread

我有非常简单的代码,但我无法理解其行为。

class Program
{
    static void Main(string[] args)
    {
        // Get reference to main thread
        Thread mainThread = Thread.CurrentThread;

        // Start second thread
        new Thread(() =>
        {
            Console.WriteLine("Working...");
            Thread.Sleep(1000);

            Console.WriteLine("Work finished. Waiting for main thread to end...");
            mainThread.Join();        // Obviously this join cannot pass

            Console.WriteLine("This message never prints. Why???");
        }).Start();

        Thread.Sleep(300);
        Console.WriteLine("Main thread ended");
    }
}

这个永无止境的程序的输出是:

Working...
Main thread ended
Work finished. Waiting for main thread to end...

为什么线程的代码卡在 Join() 方法调用上?通过其他打印输出可以发现,在Join()调用之前,mainThread的属性IsAlive设置为false,ThreadStateBackground, Stopped, WaitSleepJoin。删除睡眠也没有任何区别。

这种行为的原因是什么? Join() 方法和 Main 方法的执行背后有什么奥秘?

Join() 按照您的预期工作,这里的问题是假设线程 运行ning Main()Main() return 时终止s,但情况并非总是如此。

您的 Main() 方法由 .NET 框架调用,当方法 returns 时,框架在主线程(以及进程)退出之前执行额外的代码.具体来说,框架作为 post-Main 代码的一部分所做的事情之一是等待所有前台线程退出。

这基本上会导致典型的死锁情况 - 主线程正在等待您的工作线程退出,而您的工作线程正在等待主线程退出。

当然,如果你让你的工作线程成为后台线程,(通过在启动它之前设置 IsBackground = true)然后 post-Main 代码不会等待它退出,消除僵局。但是,您的 Join() 仍然 永远不会 return 因为当主线程退出时,进程也会退出。

有关 运行 在 Main() 之前和之后的框架内部的更多详细信息,您可以查看 GitHub 上的 .NET Core 代码库。 运行s Main()的整体方法是Assembly::ExecuteMainMethod, and the code that runs after Main() returns is Assembly::RunMainPost.