Sunday, June 3, 2012

Why use try {} finally {} with an empty try block?


I noticed in System.Threading.TimerBase.Dipose() the method has a try{} finally{} block but the try{} is empty.



Is there any value in using try{} finally{} with an empty 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;
}


Source: Tips4all

2 comments:

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


    This methodology guards against a
    Thread.Abort call interrupting the
    processing. The MSDN page of
    Thread.Abort says that “Unexecuted
    finally blocks are executed before the
    thread is aborted”. So in order to
    guarantee that your processing
    finishes even if your thread is
    aborted in the middle by someone
    calling Abort on your thread, you can
    place all your code in the finally
    block (the alternative is to write
    code in the “catch” block to determine
    where you were before “try” was
    interrupted by Abort and proceed from
    there if you want to).

    ReplyDelete
  2. This is to guard against Thread.Abort interrupting a process. Documentation for this method says that:


    Unexecuted finally blocks are executed before the thread is aborted.


    This is because in order to recover successfully from an error, your code will need to clean up after itself. Since C# doesn't have C++-style destructors, finally and using blocks are the only reliable way of ensuring that such cleanup is performed reliably. Remember that using block turns into this by the compiler:

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


    In .NET 1.x, there was a chance that finally block will get aborted. This behavior was changed in .NET 2.0.

    Moreover, empty try blocks never get optimized away by the compiler.

    ReplyDelete