Навіщо використовувати спробу {} нарешті {} з порожнім блоком спробувати?


239

Я помітив, що в 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 також: referenceource.microsoft.com/#System/services/monitoring/…
Патрік Артнер

Відповіді:


171

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

Ця методологія захищає від виклику Thread.Abort, що перериває обробку. На сторінці MSDN у Thread.Abort йдеться про те, що "Невиконані остаточно блоки виконуються до того, як потік перервано". Таким чином, щоб гарантувати, що обробка завершена, навіть якщо ваш потік перервано посередині, хтось подзвонить Abort на свою нитку, ви можете помістити весь код у остаточний блок (альтернатива - записати код у блок "catch" на визначте, де ви були до того, як "спробу" перервав Abort, і продовжте звідти, якщо хочете).


6
Чому б не використовувати msdn.microsoft.com/en-us/library/… ?
Роб Фонсека-Енсор

15
Тому що це було недоступно до .NET 2.0
Ганс Пасант

6
@ RobFonseca-Ensor: Оскільки Thread.BeginCriticalRegion()не заважає потоці перервати, швидше повідомляє час виконання, що якщо нитка перервана, то глобальна держава є корумпованою, і весь додаток до злочинства милосердя.
ккм

9
@HansPassant: BeginCriticalSection()насправді не було в .NET 1.x, але немає причини та наслідків, які ви маєте на увазі через те, що . Насправді, у .NET 1.x навіть finallyблок міг бути перерваний потоком переривання. Ці механізми служать іншій меті: виконувати роботу у finallyзапобіганні переривання середини коду, при цьому BeginCriticalSection()лише заявляє на час виконання, що глобальна держава знаходиться під загрозою.
ккм

Якщо розробник має деякий час (правда), нарешті, чи припинить коли-небудь переривання або технічний аборт може бути ігнорований на невизначений термін?
Макс Янг

64

Це захищає від Thread.Abortпереривання процесу. Документація цього методу говорить про те, що:

Невиконані остаточно блоки виконуються до переривання потоку.

Це тому, що для успішного відновлення після помилки ваш код потрібно буде очистити після себе. Оскільки у C # немає деструкторів у стилі C ++, finallyа usingблоки є єдиним надійним способом забезпечити надійне виконання такого очищення. Пам'ятайте, що usingблок перетворюється на це компілятором:

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

У .NET 1.x, був шанс, що це finally блок перерветься. Така поведінка була змінена в .NET 2.0.

Більше того, порожні tryблоки ніколи не оптимізуються компілятором.


Дякуємо за розуміння щодо використання блоку.
Стефан

@Anton Я розумію, що використання - це найкраща практика. Але для глузливих цілей іноді потрібно реалізувати клас обгортки, і одноразовий об'єкт стає змінною приватного класу. Якщо ми зробимо цю обгортку одноразовою, чи не GC автоматично обробляє перешкоду змінної приватного класу?
Озкан

@Ozkan GC нічого не розпоряджається автоматично. Вам потрібно буде застосувати фіналізатор, як правило, виклик a Dispose(false);. docs.microsoft.com/en-us/dotnet/standard/garbage-collection / ...
Торарінн

@Thorarin вибачте, але ви помиляєтесь, сказавши, що GC не розпоряджається (доопрацьовується) автоматично.
Озкан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.