У меня есть приложение, которое загружает внешние сборки, которые я не могу контролировать (аналогично модели плагинов, где другие люди создают и разрабатывают сборки, которые используются основным приложением). Он загружает их, создавая новые домены приложений для этих сборок, а затем, когда сборки используются, основной домен приложений выгружает их.
В настоящее время упрощенно выгружает эти сборки
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch(Exception exception)
{
// log exception
}
Однако иногда в процессе выгрузки возникают исключения, в частности CannotUnloadAppDomainException
. Насколько я понимаю, этого можно ожидать, поскольку поток в дочерних доменах приложений нельзя принудительно прервать из-за ситуаций, когда неуправляемый код все еще выполняется или поток находится в блоке finally
:
Когда поток вызывает Unload, цель
домен помечен для выгрузки.
выделенный поток пытается выгрузить
домен, и все темы в
домен прерван. Если поток делает
не прерывать, например, потому что это
выполнение неуправляемого кода, или потому что
он выполняет блок finally, затем
через некоторое время
CannotUnloadAppDomainException is
бросил в ветке, что изначально
называется Unload. Если нить то
не может быть прервана в конце концов,
целевой домен не выгружен.
Таким образом, в версии .NET Framework
Домен 2.0 не гарантированно выгружен, потому что это может быть
можно прекратить выполнение
резьб.
Меня беспокоит, что если сборка не загружена, это может привести к утечке памяти. Потенциальным решением было бы уничтожение самого основного процесса приложения, если произойдет указанное выше исключение, но я скорее избегу этого радикального действия.
Я также собирался повторить вызов разгрузки для нескольких дополнительных попыток. Возможно, такой ограниченный цикл:
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch (CannotUnloadAppDomainException exception)
{
// log exception
var i = 0;
while (i < 3) // quit after three tries
{
Thread.Sleep(3000); // wait a few secs before trying again...
try
{
AppDomain.Unload(otherAssemblyDomain);
}
catch (Exception)
{
// log exception
i++;
continue;
}
break;
}
}
Имеет ли это смысл? Должен ли я вообще пытаться разгрузиться снова? Должен ли я просто попробовать один раз и двигаться дальше? Есть ли что-то еще, что я должен сделать? Кроме того, можно ли что-нибудь сделать из основного домена приложений для управления внешней сборкой, если потоки все еще работают (имейте в виду, что другие пишут и выполняют этот внешний код)?
Я пытаюсь понять, как лучше всего управлять несколькими доменами приложений.