Зачем использовать try {} finally {} с пустым блоком try? - PullRequest
231 голосов
/ 02 февраля 2010

Я заметил в 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;
}

Ответы [ 2 ]

163 голосов
/ 02 февраля 2010

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

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

63 голосов
/ 02 февраля 2010

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

Неисполненные блоки finally выполняются перед прерыванием потока.

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...