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

C#.Net

C# Problem Overview


I noticed in System.Threading.TimerBase.Dispose() 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;
}

C# Solutions


Solution 1 - C#

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).

Solution 2 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSamuel NeffView Question on Stackoverflow
Solution 1 - C#danbenView Answer on Stackoverflow
Solution 2 - C#Anton GogolevView Answer on Stackoverflow