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

时间:2009-04-03 13:03:30

标签: c# .net c++ finalizer object-lifetime

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

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

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

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

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

4 个答案:

答案 0 :(得分:3)

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

最重要的是,在关机时运行终结器的保证方式似乎很少,但我不确定DLL可能会做些什么来导致事情采取不同的行为(也许就是那个DLL正在DLL_PROCESS_DETACH处理中执行某些操作,这使得.NET有机会处理终结器。

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

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