为啥在空的 try 块中使用 try finally ?
Posted
技术标签:
【中文标题】为啥在空的 try 块中使用 try finally ?【英文标题】:Why use try finally with an empty try block?为什么在空的 try 块中使用 try finally ? 【发布时间】:2015-12-06 10:15:15 【问题描述】:我注意到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/… 【参考方案1】:来自http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/:
这种方法可以防止 Thread.Abort 调用中断 加工。的 MSDN 页面 Thread.Abort 说“未执行 finally 块在 线程被中止”。所以为了 保证您的加工 即使您的线程是 中途被某人中止 在你的线程上调用 Abort,你可以 把你所有的代码放在最后 块(另一种方法是写 “catch”块中的代码来确定 你在“尝试”之前的位置是 被 Abort 打断并从 如果你想的话就在那里)。
【讨论】:
为什么不使用msdn.microsoft.com/en-us/library/…? 因为直到 .NET 2.0 才可用 @RobFonseca-Ensor:因为Thread.BeginCriticalRegion()
不会防止线程被中止,而是告诉运行时if线程被中止,则全局状态已损坏,整个 appdomain 都将被杀。
@HansPassant: BeginCriticalSection()
在 .NET 1.x 中确实不存在,但没有因果关系,正如您所说的 因为。事实上,在 .NET 1.x 中,即使是 finally
块也可能被线程中止中断。这些机制服务于不同的目的:在 finally
中工作可防止代码中途中止,而 BeginCriticalSection()
仅向运行时声明全局状态处于危险之中。
如果开发人员在 finally 中有一段时间(true),中止是否会完成,或者在技术上是否可以无限期地忽略中止?【参考方案2】:
这是为了防止Thread.Abort
中断进程。 Documentation 这个方法说:
未执行的 finally 块在线程中止之前执行。
这是因为为了从错误中成功恢复,您的代码需要自行清理。由于 C# 没有 C++ 风格的析构函数,finally
和 using
块是确保可靠执行此类清理的唯一可靠方法。请记住,using
块被编译器变成了这个:
try
...
finally
if(obj != null)
((IDisposable)obj).Dispose();
在 .NET 1.x 中,finally
块有可能会被中止。此行为在 .NET 2.0 中已更改。
此外,空的 try
块永远不会被编译器优化掉。
【讨论】:
感谢您对 using 块的见解。 @Anton 我知道使用是最佳实践。但是出于模拟的目的,有时需要实现一个包装类,并且一次性对象成为一个私有类变量。如果我们让这个包装器是一次性的,那么 GC 不是自动处理私有类变量的处理吗? @Ozkan GC 不会自动处理任何内容。您需要实现一个终结器,通常调用Dispose(false);
。 docs.microsoft.com/en-us/dotnet/standard/garbage-collection/…
@Thorarin 抱歉,但你说 GC 不会自动处理(完成)是错误的。以上是关于为啥在空的 try 块中使用 try finally ?的主要内容,如果未能解决你的问题,请参考以下文章
如果我在 Try 块中返回一个值,Finally 语句中的代码会触发吗?
try-catch- finally块中, finally块唯一不执行的情况是什么?
java中的“try - catch -finally”结构中的“finally”都有哪些用途
JAVA语言如何进行异常处理,关键字throws,throw,try,catch,finally分别代表啥意义在try块中抛出异常吗