Существует три вида так называемых «асинхронных исключений». Это исключение ThreadAbortException, OutOfMemoryException и упомянутое StackOverflowException. Эти исключения разрешены в любой инструкции вашего кода.
И есть также способ преодолеть их:
Самым простым является исключение ThreadAbortException. Когда текущий код выполняется в блоке finally. Исключения ThreadAbortException как бы «перемещаются» в конец блока finally. Поэтому все в блоке finally не может быть прервано исключением ThreadAbortException.
Чтобы избежать исключения OutOfMemoryException, у вас есть только одна возможность: ничего не размещать в куче. Это означает, что вам не разрешено создавать какие-либо новые ссылочные типы.
Чтобы преодолеть исключение StackOverflowException, вам нужна помощь со стороны Framework. Эта помощь проявляется в регионах с ограниченным исполнением. Требуемый стек выделяется за до фактического выполнения кода, а также дополнительно гарантирует, что код уже JIT-скомпилирован и поэтому доступен для исполнения.
Существует три формы для выполнения кода в ограниченных областях выполнения (скопировано из BCL Team Blog ):
- ExecuteCodeWithGuaranteedCleanup, безопасная форма переполнения стека для try / finally.
- Блок try / finally, которому сразу предшествует вызов RuntimeHelpers.PrepareConstrainedRegions. Блок try не ограничен, но все блоки catch, finally и fault для этой попытки:
- В качестве критического финализатора - любой подкласс CriticalFinalizerObject имеет финализатор, который охотно готовится до того, как будет выделен экземпляр объекта.
- Особый случай - метод ReleaseHandle SafeHandle, виртуальный метод, который охотно готовится до выделения подкласса и вызывается из критического финализатора SafeHandle.
Вы можете найти больше в этих сообщениях в блоге:
Области ограниченного исполнения и другие ошибки [Брайан Грюнкемейер] в блоге команды BCL.
Интернет-журнал Джо Даффи о Атомарности и ошибках асинхронных исключений , где он дает очень хороший обзор асинхронных исключений и надежности в .net Framework.