Вообще-то да, наконец-то побежит.
В следующих трех сценариях всегда будет выполняться команда finally :
- Никаких исключений не происходит
- Синхронные исключения (исключения, возникающие в ходе обычной программы).
Это включает CLS-совместимые исключения, которые происходят из System.Exception и не-CLS-совместимых исключений, которые не происходят из System.Exception. Исключения, не совместимые с CLS, автоматически включаются в исключение RuntimeWrappedException. C # не может генерировать исключения, не относящиеся к CLS, но такие языки, как C ++, могут. C # может вызывать код, написанный на языке, который может генерировать исключения, не совместимые с CLS.
- Асинхронное исключение ThreadAbortException
Начиная с версии .NET 2.0 исключение ThreadAbortException больше не будет препятствовать запуску finally. ThreadAbortException теперь поднимается до или после finally. Команда finally всегда будет выполняться и не будет прервана прерыванием потока, если попытка действительно была введена до прерывания потока.
В следующем сценарии, наконец, не будет работать:
Асинхронное исключение StackOverflowException.
Начиная с .NET 2.0 переполнение стека приведет к завершению процесса. Команда finally не будет запущена, если не будет применено дополнительное ограничение, чтобы окончательно сделать CER (область ограниченного выполнения). CER не должны использоваться в общем коде пользователя. Их следует использовать только в тех случаях, когда крайне важно, чтобы код очистки всегда выполнялся - после того, как весь процесс завершится из-за переполнения стека, и поэтому все управляемые объекты будут очищены по умолчанию. Таким образом, единственное место, в котором CER должен быть релевантным, - это ресурсы, которые выделены вне процесса, например, неуправляемые дескрипторы.
Как правило, неуправляемый код переносится каким-либо управляемым классом перед использованием пользовательским кодом. Управляемый класс-оболочка обычно использует SafeHandle для переноса неуправляемого дескриптора. SafeHandle реализует критический финализатор и метод Release, который запускается в CER, чтобы гарантировать выполнение кода очистки. По этой причине вы не должны видеть, что CER замусорены из-за кода пользователя.
Поэтому тот факт, что finally не запускается в StackOverflowException, не должен влиять на пользовательский код, так как процесс все равно будет завершен. Если у вас есть крайний случай, когда вам нужно очистить какой-то неуправляемый ресурс вне SafeHandle или CriticalFinalizerObject, то используйте CER следующим образом; но, пожалуйста, обратите внимание, что это плохая практика - неуправляемая концепция должна быть абстрагирована от управляемого класса (-ов) и соответствующих SafeHandle (-ов) по своему замыслу.
например,
// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// This is *NOT* a CER
}
finally
{
// This is a CER; guaranteed to run, if the try was entered,
// even if a StackOverflowException occurs.
}