.NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中

栏目: ASP.NET · 发布时间: 5年前

内容简介:不知你是否见过本文就来说说这种不一样的写法。你可以点开这个链接查看

不知你是否见过 try { } finally { } 代码中, try 块留空,而只往 finally 中写代码的情况呢?这种写法有其特殊的目的。

本文就来说说这种不一样的写法。

你可以点开这个链接查看 Exception 类,在里面你可以看到一段异常处理的代码非常奇怪:

// 代码已经过简化。
internal void RestoreExceptionDispatchInfo(ExceptionDispatchInfo exceptionDispatchInfo)
{
    // 省略代码。
    try{}
    finally
    {
        // 省略代码。
    }
    // 省略代码。
}

神奇之处就在于,其 try 块是空的,重要代码都放在 finally 中。那为什么会这么写呢?

在代码注释中的解释为:

We do this inside a finally clause to ensure ThreadAbort cannot be injected while we have taken the lock. This is to prevent unrelated exception restorations from getting blocked due to TAE.

翻译过来是:

finally 子句中执行此操作以确保在获取锁时无法注入 ThreadAbort 。这是为了防止不相关的异常恢复因 TAE 而被阻止。

也就是说, 此方法是为了与 Thread.Abort 对抗,防止 Thread.Abort 中断此处代码的执行。 Thread.Abort 的执行交给 CLR 管理, finally 的执行也是交给 CLR 管理。CLR 确保 finally 块执行的时候不会被 Thread.Abort 阻止。

代码在 .NET Framework 中的所有内容在这里下面。

// This is invoked by ExceptionDispatchInfo.Throw to restore the exception stack trace, corresponding to the original throw of the
// exception, just before the exception is "rethrown".
[SecuritySafeCritical]
internal void RestoreExceptionDispatchInfo(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
{
    bool fCanProcessException = !(IsImmutableAgileException(this));
    // Restore only for non-preallocated exceptions
    if (fCanProcessException)
    {
        // Take a lock to ensure only one thread can restore the details
        // at a time against this exception object that could have
        // multiple ExceptionDispatchInfo instances associated with it.
        //
        // We do this inside a finally clause to ensure ThreadAbort cannot
        // be injected while we have taken the lock. This is to prevent
        // unrelated exception restorations from getting blocked due to TAE.
        try{}
        finally
        {
            // When restoring back the fields, we again create a copy and set reference to them
            // in the exception object. This will ensure that when this exception is thrown and these
            // fields are modified, then EDI's references remain intact.
            //
            // Since deep copying can throw on OOM, try to get the copies
            // outside the lock.
            object _stackTraceCopy = (exceptionDispatchInfo.BinaryStackTraceArray == null)?null:DeepCopyStackTrace(exceptionDispatchInfo.BinaryStackTraceArray);
            object _dynamicMethodsCopy = (exceptionDispatchInfo.DynamicMethodArray == null)?null:DeepCopyDynamicMethods(exceptionDispatchInfo.DynamicMethodArray);
            
            // Finally, restore the information. 
            //
            // Since EDI can be created at various points during exception dispatch (e.g. at various frames on the stack) for the same exception instance,
            // they can have different data to be restored. Thus, to ensure atomicity of restoration from each EDI, perform the restore under a lock.
            lock(Exception.s_EDILock)
            {
                _watsonBuckets = exceptionDispatchInfo.WatsonBuckets;
                _ipForWatsonBuckets = exceptionDispatchInfo.IPForWatsonBuckets;
                _remoteStackTraceString = exceptionDispatchInfo.RemoteStackTrace;
                SaveStackTracesFromDeepCopy(this, _stackTraceCopy, _dynamicMethodsCopy);
            }
            _stackTraceString = null;

            // Marks the TES state to indicate we have restored foreign exception
            // dispatch information.
            Exception.PrepareForForeignExceptionRaise();
        }
    }
}

需要说明的是,.NET Core 中是没有这段内容的,你可以查看 System.Runtime.cs · dotnet/corefx 的大约 1166 行, Exception 类型是有运行时实现的。

参考资料

本文会经常更新,请阅读原文: https://walterlv.com/post/empty-try-block.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

.NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接:https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

思想的未来

思想的未来

(美)劳伦斯﹒莱斯格 / 李旭 / 中信出版社 / 2004-10 / 29.00元

因特网革命已到来,一些人说它已经过去,革命缘何而来?又缘何而去呢? 劳伦斯·莱斯格对因特网革命中为何会出现一种反革命的破坏性力量及后果做出了解释。创作之所以繁荣,是因为因特网保护了创新的公共资源。是因为因特网保护了创新的公共资源。因特网的独特设计营造出一个中立的平台。最广大范围的作者们可在此平台上进行试验。围绕此平台的法律架构对这一自由空间给予了保护,以使文化和信息——我们这个时代的......一起来看看 《思想的未来》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具