C#无法加入主线程
Posted
技术标签:
【中文标题】C#无法加入主线程【英文标题】:C# Cannot join main thread 【发布时间】:2018-12-05 13:35:29 【问题描述】:我有非常简单的代码,我无法理解它的行为。
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");
这个永无止境的程序的输出是:
在职的... 主线程结束 工作完成。等待主线程结束...为什么线程的代码卡在Join()
方法调用上?通过其他打印输出可以发现,在Join()
调用之前,mainThread
的属性IsAlive
设置为false,ThreadState
为Background, Stopped, WaitSleepJoin
。消除睡眠也没有任何区别。
这种行为的原因是什么? Join()
方法和Main
方法的执行到底有什么奥秘?
【问题讨论】:
主线程终止通常与进程终止同时发生。我猜这是对你的代码做你不想要的事情 【参考方案1】:Join()
按您的预期工作,这里的问题是假设运行Main()
的线程在Main()
返回时终止,但情况并非总是如此。
.NET 框架调用您的Main()
方法,当方法返回时,框架会在主线程(以及进程)退出之前执行额外的代码。具体来说,框架作为 post-Main 代码的一部分所做的事情之一是等待所有前台线程退出。
这实质上会导致典型的死锁情况 - 主线程正在等待您的工作线程退出,而您的工作线程正在等待主线程退出。
当然,如果你让你的工作线程成为后台线程(通过在启动它之前设置IsBackground = true
),那么后Main 代码将不会等待它退出,从而消除了死锁。但是您的Join()
将仍然永远不会返回,因为当主线程退出时,进程也会退出。
有关在 Main()
之前和之后运行的框架内部的更多详细信息,您可以查看 GitHub 上的 .NET Core 代码库。运行Main()
的整体方法是Assembly::ExecuteMainMethod
,运行之后Main()
返回的代码是Assembly::RunMainPost
。
【讨论】:
是的,这比我的回答要好。 +1用于链接源。我正打算自己做。 这是非常好的解释。我也很高兴链接的支持该声明的源代码。我不知道在哪里可以找到这段代码。 只是 mainThread 状态和 isAlive 属性值令人困惑。这也有原因吗?以上是关于C#无法加入主线程的主要内容,如果未能解决你的问题,请参考以下文章