我有一个.NET C#/ C ++应用程序,它使用一个线程中的exit(0)
(来自<stdlib.h>
)来终止。
奇怪的是,在某些情况下,托管对象的终结器在调用exit
之后立即被调用,而在其他情况下,它们根本不被调用。
情况非常确定 - 应用程序在其生命周期内从外部插件dll(用非托管C编写)调用一些方法。
如果我使用dll A,则始终调用终结器
如果我使用dll B,则永远不会调用终结器。
退出(0)调用时终结器的预期行为是什么? (如果有任何预期的和记录在案的行为)
对外部dll的调用是否会改变一些可能影响进程终止方式的全局设置?
答案 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。
在我的书中,不应该依赖终结器来运行时调用它们。处理是明确的,你可以对它进行更精细,更确定的控制。