Я испытываю затруднения при понимании чего-то о моем AppDomain.Unload(...)
звонить. У меня есть подробное объяснение с кодом от моего более раннего вопроса. Как оказалось, я выполнял несколько шагов, что, по-видимому, я не должен. Однако я вполне уверен что, когда AppDomain создан и затем сохранен в наборе:
private static Dictionary HostDomains;
void StartNewDomain(string domainName)
{
AppDomain domain = AppDomain.CreateDomain(domainName);
HostDomains[domainName] = domain;
}
... когда Вы сделаны с ним, необходимо разгрузить его:
if (HostDomains.ContainsKey(domainName))
{
AppDomain.Unload(HostDomains[domainName]);
HostDomains.Remove(domainName);
}
затем удалите домен из набора.
Когда я разгружаю домен, однако, целое приложение заканчивается. Если я удаляю разгружение, все хорошо..., и нас просто оставляют с удалением домена от набора. Но я боюсь, что мой дочерний AppDomain действительно не разгружен. Это может в конечном счете получить GC'd, который я предполагаю, но это не дает мне теплое нечеткое.
Дочерний блок AppDomain (приложение Windows Form) запускается асинхронно через интерфейс (IModule), на который ссылаются в моем классе адаптера, который наследовался MarshalByRefObject
. Я задаюсь вопросом, не упорядочивает ли эта ссылка на Запуск IMODULE () (который реализует сменная модульная конструкция) правильно (из-за моей реализации). Так, когда Завершение работы () метод называют, целое приложение умирает. Я должен сделать свой IModule абстрактным классом вместо этого, таким образом, он должен наследовать MBR также? Озадаченный...
После рассмотрения моего кода:
// instances the module for access to the module's Start() method
IModule module = (IModule)domain.CreateInstanceAndUnwrap(
ModuleManager.Modules[modName].Name,
ModuleManager.Modules[modName].EntryPoint.FullName);
... мой страх состоит в том, что, так как IModule является интерфейсом, даже при том, что я создаю экземпляр в дочернем домене, блок просачивается в мой основной AppDomain. Поэтому, когда я пытаюсь разгрузить дочерний домен, оба домена разгружаются. Это было бы корректно? И каково, вероятно, было бы лучшее решение обеспечить, Запускаются () и Остановка () методы через MBR (адаптер) объект?
ОБНОВЛЕНИЕ: см. мой ответ ниже для изменений-
Хорошо, нет никакой утечки - все наследовало MBR:
Я делаю что-то не так все еще? Я попробовал несколько вещей, и это просто, кажется, неправильно или неполно. Когда я говорю ModuleAdapter завершать работу, он звонит AppDomain.Unload(AppDomain.CurrentDomain)
и домен Host останавливается также. Я все еще получаю некоторые первые случайные исключения на выходе приложения. Но форма (myForm) была сказана.Close ().
Так, я все еще ищу корректный способ сделать это...
Как я и подозревал, создание экземпляра с интерфейсом IModule в основном домене вызывает утечку. Чтобы сделать это правильно:
AppDomain domain = AppDomain.CreateDomain(domainName);
HostDomains[domainName] = domain; // put in collection
ModuleAdapter adapter = (ModuleAdapter)domain.CreateInstanceAndUnwrap(asmName , typeName);
где ModuleAdapter наследует MarshalByRefObject
. Затем:
adapter.Execute(moduleAssembly , moduleType);
Внутри класса ModuleAdapter:
public void Execute(string Name, string EntryPoint)
{
module = (IModule)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(Name , EntryPoint);
}
Я приветствую комментарии или дополнительные ответы для лучшего способа.
После перемещения экземпляра в класс ModuleAdapter у нас все еще есть проблема с AppDomain.Unload, убивающая все приложение. Мне было интересно, связано ли это с тем, что в плагине модуля мы используем Application.Run (myForm)
- тогда, когда мы завершаем работу, мы вызываем myForm.Close (). Очевидно, это завершает работу приложения, поэтому мне было интересно, «выгружает» ли myForm.Close () также AppDomain.