Зачем использовать try {} finally {} с пустым блоком try?

Я заметил в System.Threading.TimerBase.Dipose() метод имеет блок try{} finally{}, но try{} пуст.

Есть ли какое-либо значение при использовании try{} finally{} с пустой попыткой?

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;
}

Ответ 1

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

Эта методология защищает Thread.Abort прерывает вызов обработка. Страница MSDN Thread.Abort говорит, что "Unexecuted наконец, блоки выполняются до нить отменена". Поэтому для того, чтобы гарантируйте, что ваша обработка заканчивается, даже если ваша нить прерывается посередине кем-то вызов Abort в вашей теме, вы можете поместите весь свой код в блок (альтернативой является запись кода в блоке "catch" для определения где вы были, прежде чем "попробовать" было прерван Abort и исходит из там, если вы хотите).

Ответ 2

Это защита от Thread.Abort прерывания процесса. Документация для этого метода говорит, что:

Незавершенные блоки finally выполняются до того, как поток будет прерван.

Это связано с тем, что для успешного восстановления из-за ошибки ваш код нужно будет очистить после себя. Поскольку С# не имеет деструкторов в стиле С++, блоки finally и using являются единственным надежным способом обеспечения надежной работы такой очистки. Помните, что блок using превращается в это компилятором:

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

В .NET 1.x была вероятность того, что блок finally будет прерван. Это поведение было изменено в .NET 2.0.

Кроме того, пустые блоки try никогда не будут оптимизированы компилятором.