【问题标题】:Stopping Application Loop in secondary AppDomain在辅助 AppDomain 中停止应用程序循环
【发布时间】:2010-02-19 00:27:59
【问题描述】:

首先,对篇幅表示歉意……

我有一个类似于 MAF 的主机/插件应用程序。我们没有使用任何 System.Addin 或关联的命名空间,因为这是一个自定义插件架构,其中包含多个 AppDomain。 Host 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 工作正常。当再次双击列表视图项时,模块应该关闭:

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”类型的异常,但未在用户代码中处理

不用说,我们从来没有达到我们的OnModuleStopped 事件,我们正式卸载 AppDomain 并从我们的集合中删除它和适配器。我现在放了一个 try/catch 块,看看我是否能从错误中得到更多。据我了解,我在退出应用程序消息循环然后卸载域时遵循正确的程序。这使模块能够清理其资源等。

谁能告诉我我做错了什么和/或我应该怎么做?

【问题讨论】:

    标签: c# .net-3.5 asynchronous appdomain


    【解决方案1】:

    这可能会有所帮助...

    在您的应用中,订阅:

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

    (请参阅帮助,它们可能会使事情变得更容易,但其他时候在调试模式下您会希望关闭它)

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

    也许看看像 NUnit 这样的工具是如何加载和卸载 AppDomain 的——我从来没有尝试过卸载......

    PK :-)

    【讨论】:

    • @Paul:我会尝试看看会发生什么。由于模块在它自己的 AppDomain 中运行,因此 Applicin.Exit() 应该没问题,AFAIK。
    • @Paul:事实证明,我的线程问题可能比我想象的要大。但如果是这种情况就没有意义,因为它似乎挂起的地方应该在主 AppDomain 的主线程上。 :/ 仍在努力...
    • 标记为答案。我做了一些更多的测试并调用 AppDomain.Unload(...) 导致了一个问题。这将是一个新问题。
    • 酷 - 好吧,因为它有帮助!
    • @Paul:总而言之,这让我做了一些修剪。显然我做错了什么,因为子域上的 AppDomain.Unload(..) 不应该影响主应用程序的域。 :( 这里:stackoverflow.com/questions/2294474/…
    猜你喜欢
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    相关资源
    最近更新 更多