简体   繁体   English

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

[英].NET - Finalizers and exit(0)

I have a .NET C# / C++ app which uses a call to exit(0) (from <stdlib.h> ) in a thread in order to terminate. 我有一个.NET C#/ C ++应用程序,它使用一个线程中的exit(0) (来自<stdlib.h> )的调用来终止。

The strange part is, under some circumstances, the finalizers of the managed objects are called right after the call to exit , and in other circumstances, they are not called at all. 奇怪的是,在某些情况下,托管对象的终结器在调用exit后立即被调用,而在其他情况下,它们根本不被调用。

The circumstances are pretty deterministic - the app calls some methods from an external plugin dll (written in unmanaged C) during its lifetime. 这种情况非常确定 - 应用程序在其生命周期内从外部插件dll(用非托管C编写)调用一些方法。
If I use dll A, the finalizers are always called. 如果我使用dll A,则始终调用终结器。
If I use dll B, the finalizers are never called. 如果我使用dll B,则永远不会调用终结器。

What's the expected behaviour of finalizers in case of an exit(0) call? 在退出(0)调用的情况下,终结器的预期行为是什么? (if there is any expected -and documented- behaviour) (如果有任何预期的和记录在案的行为)

Can the calls to the external dlls change some global setting that may impact the way the process is terminated? 对外部dll的调用是否会改变一些可能影响进程终止方式的全局设置?

Chris Brumme talked about how finalizers are handled during process shutdown: Chris Brumme谈到了在流程关闭期间如何处理终结器:

The bottom line is that there seems to be very little in the way of guarantees for finalizers running at shutdown, but I'm not sure what the DLLs may be doing to causing things to act differently (maybe it 's that one DLL is doing something in DLL_PROCESS_DETACH processing that's giving .NET the opportunity to process finalizers. 最重要的是,在关机时运行的终结器的保证方式似乎很少,但我不确定DLL可能做些什么导致事情采取不同的行为(也许是一个DLL正在做的事情) DLL_PROCESS_DETACH处理中的一些东西让.NET有机会处理终结器。

The article is for .NET 1.x - I'm not sure how much of this has changed in .NET 2.0 or later. 本文适用于.NET 1.x - 我不确定.NET 2.0或更高版本中有多少更改。

According to Jeff Richter's book, the system does attempt to call finalizers at process shutdown, but there is both a per-finalizer (2s) and a total-finalization (40s) timeout covering this process, after which the process is aborted. 根据Jeff Richter的书,系统确实尝试在进程关闭时调用终结器,但是有一个per-finalizer(2s)和一个完成终止(40s)超时覆盖此过程,之后进程被中止。 (Of course, the exact times might have changed by now, that was right for 2.0) (当然,到目前为止,确切的时间可能已经改变,这对2.0来说是正确的)

Could you be seeing a finalizer which takes more than 2 seconds to run? 你能看到一个超过2秒的终结器吗? That will cause finalisation to cease. 这将导致终止停止。

Ultimately this is an "arms race" problem. 最终这是一场“军备竞赛”问题。 Someone logs a bug at Microsoft complaining that their finalizers aren't running when some nasty code makes the process exit - so that problem gets fixed. 有人在微软记录一个错误,抱怨他们的终结器没有运行,当一些讨厌的代码使进程退出时 - 这个问题得到解决。 Then someone else logs a bug about how there doesn't seem to be a way to force the process to exit instantly so that finalizers don't run, so Microsoft adds a new API to allow that again. 然后其他人记录了一个错误,该错误似乎没有办法强制进程立即退出,以便终结器不会运行,因此Microsoft添加了一个新的API来再次允许它。 So another person demands a new kind of "critical" finalizer that always runs even in response to that new kind of exit... and so on. 因此,另一个人需要一种新的“关键”终结器,即使在响应新的退出时也总是运行...等等。

So it would probably be easier to change the C++ code than to try and rely on who is currently winning the arms race. 因此,改变C ++代码可能比尝试依赖谁正在赢得军备竞赛更容易。

If the code you put in finalizers is rather critical, move it to Dispose and put a call to Dispose in your finalizers with if( !disposed ) pattern in Dispose. 如果放在终结器中的代码非常关键,请将其移至Dispose,并在Dispose中使用if(!dispos)模式在终结器中调用Dispose。

In my book, finalizers shouldn't be relied upon to ever be called by runtime. 在我的书中,不应该依赖终结器来运行时调用它们。 Dispose is explicit and you have much finer, and deterministic control over it. 处理是明确的,你有更精细,更确定的控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM