4

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

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

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

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

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

4

4 回答 4

3

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

最重要的是,对于在关闭时运行的终结器的保证方式似乎很少,但我不确定 DLL 可能会做什么来导致事情发生不同(也许是一个 DLL 正在做DLL_PROCESS_DETACH 处理中的某些内容使 .NET 有机会处理终结器。

这篇文章是针对 .NET 1.x 的——我不确定在 .NET 2.0 或更高版本中有多少变化。

于 2009-04-03T13:15:21.163 回答
3

根据 Jeff Richter 的书,系统确实会尝试在进程关闭时调用终结器,但是在此过程中,每个终结器(2 秒)和总终结器(40 秒)都超时,之后进程被中止。(当然,现在可能已经改变了确切的时间,这对 2.0 来说是正确的)

你能看到一个运行时间超过 2 秒的终结器吗?这将导致最终确定停止。

于 2009-04-03T13:26:20.420 回答
2

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

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

于 2009-04-03T13:33:31.867 回答
2

如果您放入终结器中的代码相当关键,请将其移至 Dispose 并在 Dispose 中使用 if(!disposed) 模式调用终结器中的 Dispose。

在我的书中,不应该依赖终结器来被运行时调用。Dispose 是显式的,您可以对其进行更精细和确定性的控制。

于 2009-04-11T15:11:48.433 回答