问题描述
首先,抱歉篇幅过长...
First off, apologies for the length...
我有一个类似于 MAF 的主机/插件应用程序.我们没有使用任何 System.Addin 或关联的命名空间,因为这是一个自定义插件架构,其中包含多个 AppDomains.主机 UI(用户界面)在它自己的应用程序循环 (AppDomain) 中运行.当双击列表视图中的项目时,会发生以下情况:
I have a Host/Plugin application akin to MAF. We are not using any of the System.Addin or associated namespaces as this is a custom plugin architecture with multiple AppDomains in play. The Host UI (user interface) is running in it's own application loop (AppDomain). When an item in a listview is double-clicked the following occurs:
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
只是告诉主机模块插件正在通过插件的 UI 关闭,并开始在 AppDomain
上关闭程序.模块插件按预期启动,事件 OnModuleStarted
工作正常.当再次双击列表视图项时,模块应关闭:
MdiForm_FormClosed
simply tells the Host that the module plugin is being closed via the plugin's UI and to begin closing procedures on the AppDomain
. The module plugin starts as expected and the event OnModuleStarted
works fine. When the listview item is once again double-clicked the module should shut down:
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 function in module plugin:
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 '.'(点)来自轮询机制,然后:
The reason the MdiForm.FormClosed event is unsubscribed to is to prevent double firing. As soon as the Application.Exit()
I get 1 - 2 '.' (dots) from the polling mechanism and then:
System.Threading.ThreadAbortException"类型的第一次机会异常发生在 mscorlib.dll 中System.Threading.ThreadAbortException"类型的第一次机会异常发生在 UnitTestWinForm.dll 中UnitTestWinForm.dll 中出现类型为System.Threading.ThreadAbortException"的异常,但未在用户代码中处理
不用说,我们永远不会到达我们的 OnModuleStopped
事件,在那里我们正式卸载 AppDomain 并从我们的集合中删除它和适配器.我现在正在放入一个 try/catch 块,以查看是否可以从错误中获得更多信息.据我所知,我在退出应用程序消息循环然后卸载域时遵循正确的程序.这使模块能够清理其资源等.
Needless to say, we never reach our OnModuleStopped
event where we officially unload the AppDomain and remove it and the adapter from our collections. I am putting a try/catch block in now to see if I can get anything more from the errors. From what I understand, I am following the proper procedure in exiting the application message loop and then unloading the domain. This gives the module the ability to clean up it's resources, etc.
谁能告诉我我做错了什么和/或我应该如何做不同的事情?
推荐答案
这可能有帮助...
在您的应用中,订阅:
AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
Application.ThreadException += ApplicationThreadException;
(请参阅帮助,它们可能会使事情变得更容易,但有时在调试模式下您会希望关闭此功能)
(see the help, they may make things easier but other times in debug mode you'll want this off)
我认为您不应该从模块中调用 Application.Exit(),它会(据我所知)关闭整个应用程序.
I don't think you should be calling Application.Exit() from the module, it will (as far as I know) shut down the whole app.
也许看看像NUnit这样的工具是如何加载和卸载AppDomains的——我从来没有试过卸载....
Perhaps look at how A tool like NUnit loads and unloads AppDomains - I have never tried unloading one....
PK :-)
这篇关于停止辅助 AppDomain 中的应用程序循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!