在辅助AppDomain中停止应用程序循环

时间:2010-02-19 00:28:00

标签: c# .net-3.5 asynchronous appdomain

首先,道歉......

我有一个类似于MAF的主机/插件应用程序。我们没有使用任何System.Addin或相关的命名空间,因为这是一个具有多个AppDomain的自定义插件架构。主机UI(用户界面)在其自己的应用程序循环(AppDomain)中运行。双击列表视图中的项目时,会发生以下情况:

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正常工作。再次双击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(".");
    }
}

模块插件中的关机功能:

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'。' (点)来自投票机制,然后:

  

mscorlib.dll中出现'System.Threading.ThreadAbortException'类型的第一次机会异常   UnitTestWinForm.dll中出现'System.Threading.ThreadAbortException'类型的第一次机会异常   UnitTestWinForm.dll中出现“System.Threading.ThreadAbortException”类型的异常,但未在用户代码中处理

毋庸置疑,我们从未到达我们正式卸载AppDomain的OnModuleStopped事件,并从我们的集合中删除它和适配器。我现在正在尝试使用try / catch块来查看是否可以从错误中获得更多信息。据我所知,我正在遵循退出应用程序消息循环然后卸载域的正确过程。这使模块能够清理它的资源等。

任何人都可以告诉我我做错了什么和/或我应该如何做到这一点?

1 个答案:

答案 0 :(得分:1)

这可能会有所帮助......

在您的应用中,订阅:

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

(参见帮助,他们可能会让事情变得更容易,但有时候在调试模式下你会想要这样做)

我认为你不应该从模块调用Application.Exit(),它会(据我所知)关闭整个应用程序。

或许看看像NUnit这样的工具如何加载和卸载AppDomains - 我从来没有试过卸载过一个....

PK: - )