ExecuteCodeWithGuaranteedCleanup 何时真正保证清理?

发布于 2024-08-27 23:06:07 字数 1803 浏览 5 评论 0原文

我一直在阅读.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 does 被调用(但是常规的 try...finally 也可以捕获此异常)

Thread.CurrentThread.Abort();

所以问题是

  • 我是否正确使用了 ExecuteCodeWithGuaranteedCleanup?
  • ExecuteCodeWithGuaranteedCleanup 什么时候真正有用?

I have been reading about Reliability Features in .NET and have written the following class to explore 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();
    }
}

I have experimented with a variety of code bodies for the Code method. These, and their runtime results are listed below

Causing an OutOfMemoryException - Cleanup does not get called

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

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

    ss.Add(s);
}

Causing a StackOverflowException - Cleanup does not get called

Code(message); // recursive call

Causing a ExecutionEngineException - Cleanup does not get called

Environment.FailFast(message.ToString());

Causing a ThreadAbortException - Cleanup does get called (however a regular try...finally can also catch this exception)

Thread.CurrentThread.Abort();

So the questions are

  • Am I using ExecuteCodeWithGuaranteedCleanup correctly?
  • When is ExecuteCodeWithGuaranteedCleanup actually useful?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

呆萌少年 2024-09-03 23:06:07

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

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

Some exceptions are fatal to the process and execution of user-supplied code just does not continue. The purpose of ExecuteCodeWithGuaranteedCleanup method is to so you can put your data structures back in a consistent state. If the process is going to die anyways with no way to stop it, this has no purpose. The OS (assuming it is working properly) will clean up any kernel objects automatically for you when a process ends, regardless of the reason the process ends.

As Hans hints, the ICLRPolicyManager of the host comes into play to determine which exceptions are fatal in this way when code is run in a particular host (especially SQL Server). See the nice grid at the bottom of this documentation page: ICLRPolicyManager::SetActionOnFailure Method

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文