Прежде всего, извинения за длину ...Остановка аппликационной петли во вторичном AppDomain
У меня есть приложение Host/Plugin, похожее на MAF. Мы не используем ни одно из System.Addin или связанных пространств имен, поскольку это настраиваемая архитектура плагина с несколькими приложениями в игре. Интерфейс хоста (пользовательский интерфейс) работает в своем собственном цикле приложений (AppDomain). Когда элемент в ListView двойном щелчке происходит следующее:
private static void StartPeripheralModule(string modName)
{
AppDomain domain = AppDomain.CreateDomain(modName);
// add to appdomains collection
HostDomains[modName] = domain;
// 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);
// instance the adapter (inherits MBR)
module.Adapter = new ModuleAdapter(modName, module); // also saves a ref. to the IModule object
// publish events decorated with [Serializable]
module.Adapter.ModuleStarted += new ModuleAdapter.ModuleStartEventHandler(Adapter_ModuleStarted);
module.Adapter.ModuleStopped += new ModuleAdapter.ModuleStopEventHandler(Adapter_ModuleStopped);
module.Adapter.ModuleFaulted += new ModuleAdapter.ModuleFaultEventHandler(Adapter_ModuleFaulted);
// add to adapters collection
HostAdapters[modName] = module.Adapter;
// asynchronous startup
Action startup = module.Start;
startup.BeginInvoke(null , null);
}
В module.Start()
:
[STAThread]
public void Start()
{
// do Start
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MdiForm = new UnitMDIForm();
MdiForm.FormClosed += new FormClosedEventHandler(MdiForm_FormClosed);
adapter.OnModuleStarted(new ModuleAdapter.ModuleStartEventArgs(adapter));
Application.Run(MdiForm);
}
MdiForm_FormClosed
просто сообщает хосту, что подключаемый модуль закрывается с помощью пользовательского интерфейса плагина и начать процедуры закрытия на AppDomain
. Плагин модуля запускается, как ожидалось, и событие OnModuleStarted
работает нормально. Когда элемент ListView снова дважды щелкнул модуль должен выключить: функцию
public static void UnloadInstance(string modName)
{
Action shutdown = HostAdapters[modName].Module.Shutdown;
IAsyncResult iaRes = shutdown.BeginInvoke(null , null);
while (!iaRes.IsCompleted) // poll wait state
{
Thread.Sleep(250);
hostListener.Write(".");
}
}
Shutdown в модуле плагина:
public void Shutdown()
{
if (MdiForm.InvokeRequired)
{
MdiForm.Invoke((MethodInvoker)delegate
{
MdiForm.FormClosed -= MdiForm_FormClosed;
Application.Exit();
});
}
else
{
MdiForm.FormClosed -= MdiForm_FormClosed;
Application.Exit();
}
adapter.OnModuleStopped(new ModuleAdapter.ModuleStopEventArgs(adapter));
}
Причина событие MdiForm.FormClosed является отписался на это, чтобы предотвратить двойной обжиг. Как только Application.Exit()
получаю 1 - 2 '.' (точки) от механизма опроса и затем:
Первый шанс, исключение типа «System.Threading.ThreadAbortException» произошло в mscorlib.dll первого шанса исключение типа «System.Threading.ThreadAbortException» произошло в UnitTestWinForm.dll исключение типа «System.Threading.ThreadAbortException» произошел в UnitTestWinForm.dll, но не был обработан в пользовательском коде
Излишне говорить, что мы никогда не достигнем нашей OnModuleStopped
мероприятия, где мы официально разгружать AppDomain и удалите его и адаптер из наших коллекций. Я помещаю блок try/catch в настоящее время, чтобы увидеть, могу ли я получить что-то еще от ошибок. Насколько я понимаю, я следую правильной процедуре выхода из цикла сообщений приложения и затем выгружает домен. Это дает модулю возможность очистки своих ресурсов и т. Д.
Может ли кто-нибудь сказать мне, что я делаю неправильно и/или как я должен делать это по-другому?
@Paul: Я буду стараться и посмотреть, что происходит. Поскольку модуль работает в собственном AppDomain, то Applicatin.Exit() должен быть точным, AFAIK. – IAbstract
@Paul: Оказывается, у меня может быть проблема с большими потоками, чем я думал. Но это не имеет смысла, если это так, потому что, когда он, кажется, подвешен, должен находиться в главном потоке основного AppDomain. :/Все еще работаю над этим ... – IAbstract
Маркировка как ответ. Я сделал еще несколько тестов и вызвал приложение AppDomain.Unload (...). Это будет новый вопрос. – IAbstract