11

我一直在阅读.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真正有用?
4

1 回答 1

5

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

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

于 2011-12-24T01:02:26.407 回答