本文介绍了停止辅助 AppDomain 中的应用程序循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,抱歉篇幅过长...

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 中的应用程序循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 12:43