ExecuteCodeWithGuaranteedCleanup什么时候能保证清理?

时间:2010-04-07 09:45:10

标签: .net reliability

我一直在阅读Reliability Features in .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();
    }
}

我已经尝试了Code方法的各种代码体。这些及其运行时结果列在下面

导致OutOfMemoryException - Cleanup 无法被调用

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

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

    ss.Add(s);
}

导致StackOverflowException - Cleanup 无法被调用

Code(message); // recursive call

导致ExecutionEngineException - Cleanup 无法被调用

Environment.FailFast(message.ToString());

导致ThreadAbortException - Cleanup 被调用(但是常规try...finally也可以捕获此异常)

Thread.CurrentThread.Abort();

所以问题是

  • 我正确使用ExecuteCodeWithGuaranteedCleanup吗?
  • ExecuteCodeWithGuaranteedCleanup何时实际有用?

1 个答案:

答案 0 :(得分:4)

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

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