И наконец: гарантированно ли будет вызван в любом случае - PullRequest
3 голосов
/ 13 сентября 2010

Есть ли хоть небольшая вероятность, что finally не будет вызван, но приложение все еще будет работать?

Я выпускаю семафор там

        finally
        {
            _semParallelUpdates.Release();
        }

и боюсь потерять некоторыеиз них.

Ответы [ 6 ]

1 голос
/ 13 сентября 2010

Только критические финализаторы имеют сильную гарантию на случай, если дерьмо поразит поклонника.Вы можете наследовать от CriticalFinalizerObject или SafeHandle , чтобы получить это поведение.Однако, разрешать вашему финализатору делать что-либо еще, кроме кода вызова с надежным контрактом на надежность, не рекомендуется.Этот код должен запускаться, например, в ситуациях, когда системе не хватает памяти.

Реализация критического финализатора необходима только в ситуациях, когда вы хотите убедиться, что все необработанные ресурсы очищены, даже еслидомен приложения выгружен (например, потому что).Обратите внимание, что вы, конечно, никогда не можете гарантировать, что финализаторы будут работать.В случае сбоя питания вам не повезло.Если вам нужно больше гарантий, вам нужна какая-то транзакционная система (например, база данных), которая может дать вам такое поведение.

0 голосов
/ 08 сентября 2011

Текущий поток не покинет текущий кадр стека до тех пор, пока не будет выполнен блок «finally» или не будет выдано исключение из самого блока finally. Если поток умирает или блокируется в блоке try, выполнение никогда не покинет текущий кадр стека, но не выполнит и последний блок.

0 голосов
/ 13 сентября 2010

Гарантируется ли, что ваш код достигнет finally? Да (за исключением какого-то катастрофического события, такого как наступающий конец света ... или, как вы знаете, потеря вашего компьютера или сбой вашей ОС).

Но важно понимать, что если абсолютно необходимо, чтобы ваш код выполнялся, вам лучше убедиться, что ваш код не вызывает само исключение!

Возьмем, к примеру, это:

IDisposable someDisposableObject = null;
IDisposable someOtherDisposableObject = null;

try
{
    someDisposableObject = GetDisposableObject();

    throw new Exception("Holy crap, something bad happened.");

    someOtherDisposableObject = GetOtherDisposableObject();
}
finally
{
    // This will throw a NullReferenceException...
    someOtherDisposableObject.Dispose();

    // ...so this actually won't run.
    someDisposableObject.Dispose();
}

Поэтому, если вы хотите, чтобы ваш весь finally блок был запущен, важно написать его правильно, чтобы исключение (в идеале) было невозможным.

0 голосов
/ 13 сентября 2010

Если вы ищете способы сделать ваш код надежным, я предлагаю прочитать следующую статью:

Рекомендации по надежности

Еще одна отличная статья, рекомендованная VinayC:

Стивен Тауб: Поддерживайте работу своего кода с помощью функций надежности .NET Framework

0 голосов
/ 13 сентября 2010

В Framework 1.0 и 1.1 это было возможно , если поток, находящийся в данный момент в блоке finally, был прерван с использованием Thread.Abort. В текущих версиях фреймворка я не знаю ни о каких подобных случаях.

0 голосов
/ 13 сентября 2010

Операционная система Windows хоста прекратит работу программы даже в наихудших случаях неосознанных фатальных исключенийНо даже в этом случае блок finally обязательно будет выполнен.

...