ExecuteCodeWithGuaranteedCleanup什么时候保证清理?

Ric*_*ett 9 .net reliability

我一直在阅读.NET中的可靠性功能,并编写了以下类来进行探索ExecuteCodeWithGuaranteedCleanup

class Failing
{
    public void Fail()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        try
        {
        }
        finally
        {
            RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(Code, Cleanup, "fail");
        }
    }

    private void Code(object message)
    {
        // Some code in here that will cause an exception...
    }

    private void Cleanup(object message, bool something)
    {
        Console.WriteLine(message);
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经为该Code方法试验了各种代码体.下面列出了这些及其运行时结果

导致OutOfMemoryException- Cleanup 不会被召唤

List<string> ss = new List<string>();

while (true)
{
    string s = new string('x', 1000000);

    ss.Add(s);
}
Run Code Online (Sandbox Code Playgroud)

导致StackOverflowException- Cleanup 不会被召唤

Code(message); // recursive call
Run Code Online (Sandbox Code Playgroud)

导致ExecutionEngineException- Cleanup 不会被召唤

Environment.FailFast(message.ToString());
Run Code Online (Sandbox Code Playgroud)

造成ThreadAbortException- Cleanup 被调用(但经常try...finally也可以捕获这个异常)

Thread.CurrentThread.Abort();
Run Code Online (Sandbox Code Playgroud)

所以问题是

  • 我使用ExecuteCodeWithGuaranteedCleanup得当吗?
  • 什么时候ExecuteCodeWithGuaranteedCleanup实际有用?

Jas*_*aty 5

一些异常对进程来说是致命的,用户提供的代码的执行不会继续。ExecuteCodeWithGuaranteedCleanup方法的目的是使您可以将数据结构恢复到一致状态。如果进程无论如何都将终止而无法阻止它,那么这没有任何意义。操作系统(假设它工作正常)会在进程结束时自动为您清理任何内核对象,而不管进程结束的原因。

正如 Hans 所暗示的那样,ICLRPolicyManager当代码在特定主机(尤其是 SQL Server)中运行时,主机的 以这种方式确定哪些异常是致命的。请参阅本文档页面底部的漂亮网格:ICLRPolicyManager::SetActionOnFailure Method