Я не знаю прямого ответа.
Если вы хотите написать надежную DLL, вам следует подготовиться к нескольким сценариям:
- Ваш код размещается в приложении .NET в домене приложений по умолчанию. (тривиальный сценарий)
- Ваш код размещается в приложении .NET в AppDomain, созданном кодом хоста.
- Ваш код размещается в неуправляемом приложении (в котором размещается среда CLR).
С третьим сценарием сложнее всего справиться, поскольку CLR может быть отключена хостом, поэтому управляемый код больше не будет выполняться.
System.Windows.Forms.Application.ApplicationExit
не годится, так как применяется только к приложениям WinForm.
System.AppDomain.DomainUnload
сам по себе бесполезен, так как он никогда не поднимается для AppDomain по умолчанию.
AppDomain.ProcessExit
сам по себе бесполезен: если ваш код размещен в отдельном AppDomain, хост может выгрузить этот AppDomain, поэтому событие никогда не возникнет.
Я бы начал с попытки охватить большинство случаев, используя что-то вроде:
if (AppDomain.CurrentDomain.IsDefaultAppDomain())
AppDomain.CurrentDomain.ProcessExit += MyTerminationHandler;
else
AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler;
Но обратите внимание на следующее замечание (из MSDN):
Общее время выполнения всех обработчиков событий ProcessExit ограничено, так же как общее время выполнения всех финализаторов ограничено при завершении процесса. По умолчанию две секунды. Неуправляемый узел может изменить это время выполнения, вызвав метод ICLRPolicyManager::SetTimeout со значением перечисления OPR_ProcessExit.
Приведенный выше код по-прежнему оставляет третий сценарий без присмотра. Я знаю два метода работы с этим сценарием (вместе с первыми двумя).
Во-первых, вы можете использовать метод System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup
следующим образом:
{
// this goes at your code's entry point
RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(MyExecutionCode, MyCleanupCode, null);
}
static void MyExecutionCode(object data) { /* your execution code here */}
static void MyCleanupCode(object data, bool exceptionThrown) { /* your cleanup code here */ }
Во-вторых, вы можете использовать класс System.Runtime.ConstrainedExecution.CriticalFinalizerObject
(см. MSDN здесь), унаследовав его и поместив код очистки в финализатор. Для этого код очистки должен соответствовать рекомендациям Ограниченная область выполнения.
person
M.A. Hanin
schedule
21.05.2013