我不知道有没有直接的答案。
如果你想编写一个强大的DLL,你应该为几种情况做好准备:
1. 你的代码在.NET应用程序中托管,在默认的AppDomain中。(最简单的情况)
2. 你的代码在.NET应用程序中托管,在由主机代码创建的AppDomain中。
3. 你的代码在未托管的应用程序中托管(它托管CLR)。
第三种情况是最难处理的,因为CLR可能会被其主机禁用,所以托管代码将不再执行。
System.Windows.Forms.Application.ApplicationExit并不好用,因为它只适用于WinForm应用程序。
仅使用System.AppDomain.DomainUnload也不好用,因为它永远不会为默认AppDomain引发。
仅使用AppDomain.ProcessExit也不好用:如果你的代码托管在一个单独的AppDomain中,主机可能会卸载该AppDomain,因此事件将永远不会引发。
我会尝试覆盖大多数情况,使用类似以下的内容开始:
if (AppDomain.CurrentDomain.IsDefaultAppDomain())
AppDomain.CurrentDomain.ProcessExit += MyTerminationHandler;
else
AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler;
请注意以下备注(
来自MSDN):
所有ProcessExit事件处理程序的总执行时间是有限制的,就像进程关闭时所有终结器的总执行时间一样。默认值为两秒钟。非托管宿主可以通过使用OPR_ProcessExit枚举值调用ICLRPolicyManager :: SetTimeout方法来更改此执行时间。
上面的代码仍然没有涉及第三种情况。我知道有两种方法可以处理这种情况(以及前两种方法)
首先,您可以使用System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup方法,如下所示:
{
RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(MyExecutionCode, MyCleanupCode, null);
}
static void MyExecutionCode(object data) { }
static void MyCleanupCode(object data, bool exceptionThrown) { }
其次,您可以利用
System.Runtime.ConstrainedExecution.CriticalFinalizerObject
类(
在此处查看MSDN)通过继承它并将清理代码放在 finalizer 中来进行清理。这要求您的清理代码遵循
约束执行区域 指南。