我以前注意到过这种行为,这次我想问一个问题:
我有一个简单的“概念验证”程序,它生成几个线程,等待它们完成一些工作,然后退出。
但是 Main
不会返回,除非我调用 server.Close()
(它会关闭套接字并结束服务器线程的执行):
private void Run()
{
var server = StartServer(); //Starts a thread in charge of listening on a socket
_serverResetEvent.WaitOne();
ThriftProtocolAccessManager protocolManager = CreateProtocolManager(); //Doesn't create any threads
const int numTestThreads = 10;
Barrier testCompletedBarrier;
Thread[] testThreads = GenerateTestThreads(numTestThreads, protocolManager, out testCompletedBarrier); //Creates x threads, where x is numTestThreads
testThreads
.AsParallel()
.ForAll(thread => thread.Start()); //Start them "at the same time" (For testing purposes
testCompletedBarrier.SignalAndWait(); //Barrier has participants equal to numTestThreads + 1 and each thread calls this
//server.Close() would go here. When it is here, the program returns as expected
Console.WriteLine("All Threads Complete"); //This is getting called
}
private static void Main(string[] args)
{
new Program().Run();
Console.WriteLine("Run completed"); //This is also called
}//The debugger confirms this brace is reached as well
根据 ECMA C# 语言规范的第 10.2 条“应用程序终止”:
If the return type of the entry point method is
void
, reaching the right brace (}
) which terminates that method, or executing areturn
statement that has no expression, results in a termination status code of 0.
调试器确认到达正确的大括号,但标准并未明确说明离开 Main
将退出应用程序,只是设置了终止状态代码。
它还提到:
...finalizers for all of [the application's] objects that have not yet been garbage collected are called, unless such cleanup has been suppressed (by a call to the library method
GC.SuppressFinalize
, for example).
我怀疑幕后的终结器可能是问题所在,因为服务器对象实现了 IDisposable
,并且调用 Dispose
的终结器并不少见。但是当程序被终止时,CLR 将终结器限制为两秒的执行(以防万一超时发生了一些奇怪的事情我尝试在服务器对象上调用 GC.SuppressFinalize
并得到相同的结果).
我对服务器线程可以做什么来无限期地阻止应用程序终止感到有点困惑。
最佳答案
@Carsten König 链接中使用的措辞让我意识到我在查找错误的文档。问题确实是启动服务器实现的线程是前台线程,将其更改为后台线程会导致 ThreadPool 实现按预期运行。
ECMA 标准似乎推迟了特定的终止行为(CLI 文档也没有提及任何相关内容)。我仍在寻找是否可以找到更详细地描述整个终止程序的通用文档。
关于c# - 为什么 Main 还没有回来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25325798/