2010-02-19 2 views
1

Прежде всего, извинения за длину ...Остановка аппликационной петли во вторичном 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 в настоящее время, чтобы увидеть, могу ли я получить что-то еще от ошибок. Насколько я понимаю, я следую правильной процедуре выхода из цикла сообщений приложения и затем выгружает домен. Это дает модулю возможность очистки своих ресурсов и т. Д.

Может ли кто-нибудь сказать мне, что я делаю неправильно и/или как я должен делать это по-другому?

ответ

1

Это может помочь ...

В приложении, подписаться на:

 AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; 
     Application.ThreadException += ApplicationThreadException; 

(см помощи, они могут сделать вещи проще, но и другие времена в режиме отладки вы хотите это off)

Я не думаю, что вы должны вызвать Application.Exit() из модуля, он (насколько мне известно) выключит все приложение.

Может быть, посмотрим, как инструмент, как NUnit нагрузок и выгружает AppDomains - Я никогда не пробовал разгрузки один ....

PK :-)

+0

@Paul: Я буду стараться и посмотреть, что происходит. Поскольку модуль работает в собственном AppDomain, то Applicatin.Exit() должен быть точным, AFAIK. – IAbstract

+0

@Paul: Оказывается, у меня может быть проблема с большими потоками, чем я думал. Но это не имеет смысла, если это так, потому что, когда он, кажется, подвешен, должен находиться в главном потоке основного AppDomain. :/Все еще работаю над этим ... – IAbstract

+0

Маркировка как ответ. Я сделал еще несколько тестов и вызвал приложение AppDomain.Unload (...). Это будет новый вопрос. – IAbstract

Смежные вопросы