为什么将try {}最终{}与空的try块一起使用?


239

我注意到System.Threading.TimerBase.Dispose()该方法中有一个try{} finally{}块,但是try{}为空。

try{} finally{}与空值一起使用是否有任何价值try

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Threading&type=TimerBase

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal bool Dispose(WaitHandle notifyObject)
{
    bool status = false;
    bool bLockTaken = false;
    RuntimeHelpers.PrepareConstrainedRegions();
    try {
    }
    finally {
        do {
            if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) {
                bLockTaken = true;
                try {
                    status = DeleteTimerNative(notifyObject.SafeWaitHandle);
                }
                finally {
                    m_lock = 0;
                }
            }
            Thread.SpinWait(1);
            // yield to processor
        }
        while (!bLockTaken);
        GC.SuppressFinalize(this);
    }

    return status;
}

周围的System.Diagnostics.Process线2144以及:referencesource.microsoft.com/#System/services/monitoring/...
帕特里克Artner

Answers:


171

http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/

这种方法可以防止Thread.Abort调用中断处理。Thread.Abort的MSDN页面说:“未执行的最终块在线程中止之前已执行”。因此,为了确保即使有人在线程上调用Abort中断了您的线程而在中间中断了处理,您也可以将所有代码放在finally块中(另一种方法是在“ catch”块中编写代码以确定在“尝试”被Abort打断之前您在哪里,然后从那里继续进行)。



15
因为直到.NET 2.0,该功能才可用
Hans Passant 2010年

6
@ RobFonseca-Ensor:因为Thread.BeginCriticalRegion()这不会阻止线程中止,而是告诉运行时如果线程中止,则全局状态已损坏,整个应用程序域都受到了残酷的杀害。
公里

9
@HansPassant:BeginCriticalSection()真的是不存在的.NET 1.x中,但没有因果关系,您在说暗示,因为。实际上,在.NET 1.x中,即使一个finally块也可能被线程中止中断。这些机制有不同的用途:在a中进行工作finally可防止代码中途中断,而BeginCriticalSection()仅向运行时声明全局状态处于危险中。
公里

如果开发人员最终有一会儿(true),那么中止会完成吗,或者中止会在技术上无限期地被忽略?
Max Young

64

这是为了防止Thread.Abort中断进程。此方法的文档说:

未执行的finally块在线程中止之前执行。

这是因为为了从错误中成功恢复,您的代码将需要自己清除。由于C#没有C ++样式的析构函数,finallyusing块是确保可靠执行此类清除操作的唯一可靠方法。请记住,using编译器将这一块变成了:

try {
    ...
}
finally {
    if(obj != null)
        ((IDisposable)obj).Dispose();
}

在.NET 1.x中,finally块有可能被中止。在.NET 2.0中,此行为已更改。

而且,空try块永远不会被编译器优化。


感谢您对using块的见识。
Stefan

@Anton我知道使用是最佳实践。但是出于模拟目的,有时需要实现包装器类,并且一次性对象成为私有类变量。如果我们使该包装器成为一次性的,那么GC是否不自动处理私有类变量的处理?
Ozkan

@Ozkan GC不会自动处理任何内容。您需要实现一个终结器,通常调用Dispose(false);docs.microsoft.com/en-us/dotnet/standard/garbage-collection/…–
Thorarin

@Thorarin对不起,但是您说GC未自动处置(最终确定)是您的错。
Ozkan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.