.NET – 终结器和退出(0)

我有一个.NET C#/ C ++应用程序,它使用一个线程中的exit(0) (来自 )来终止。

奇怪的是,在某些情况下,托管对象的终结器在调用exit后立即被调用,而在其他情况下,它们根本不被调用。

这种情况非常确定 – 应用程序在其生命周期内从外部插件dll(用非托管C编写)调用一些方法。
如果我使用dll A,则始终调用终结器。
如果我使用dll B,则永远不会调用终结器。

在退出(0)调用的情况下,终结器的预期行为是什么? (如果有任何预期的和记录在案的行为)

对外部dll的调用是否会改变一些可能影响进程终止方式的全局设置?

Chris Brumme谈到了在流程关闭期间如何处理终结器:

最重要的是,在关机时运行终结器的保证方式似乎很少,但我不确定DLL可能做些什么导致事情采取不同的行为(可能是一个DLL正在做的事情) DLL_PROCESS_DETACH处理中的一些东西让.NET有机会处理终结器。

本文适用于.NET 1.x – 我不确定.NET 2.0或更高版本中有多少更改。

根据Jeff Richter的书,该系统确实尝试在进程关闭时调用终结器,但是有一个per-finalizer(2s)和一个完成终止(40s)超时覆盖此过程,之后该过程被中止。 (当然,确切的时间可能已经改变了,这对2.0来说是正确的)

你能看到一个超过2秒的终结器吗? 这将导致终止停止。

最终这是一场“军备竞赛”问题。 有人在Microsoft记录一个错误,抱怨他们的终结器没有运行时,一些讨厌的代码使进程退出 – 这样问题就解决了。 然后,其他人记录了一个错误,该错误似乎没有办法强制进程立即退出,以便终结器不会运行,因此Microsoft添加了一个新的API以再次允许它。 因此,另一个人需要一种新的“关键”终结器,即使在响应新的退出时也始终运行…等等。

因此,更改C ++代码可能比尝试依赖谁正在赢得军备竞赛更容易。

如果放在终结器中的代码非常关键,请将其移至Dispose,并在Dispose中使用if(!dispos)模式在终结器中调用Dispose。

在我的书中,不应该依赖终结器来被运行时调用。 处理是明确的,你可以对它进行更精细,更确定的控制。