代码之家  ›  专栏  ›  技术社区  ›  IAbstract

AppDomain卸载正在终止父AppDomain

  •  8
  • IAbstract  · 技术社区  · 16 年前

    我很难弄清楚我的 AppDomain.Unload(...) 打电话。我有一个详细的解释,代码来自 my earlier question . 事实证明,我做了几步,显然,我不需要。但是,我相当肯定,当创建AppDomain并将其保存在集合中时:

    private static Dictionary<string , AppDomain> HostDomains;
    
    void StartNewDomain(string domainName)
    {
        AppDomain domain = AppDomain.CreateDomain(domainName);
        HostDomains[domainName] = domain;
    }
    

    …完成后,必须卸载:

    if (HostDomains.ContainsKey(domainName))
    {
        AppDomain.Unload(HostDomains[domainName]);
        HostDomains.Remove(domainName);
    }
    

    然后从集合中删除域。

    但是,当我卸载域时,整个应用程序将结束。如果我删除卸载,一切都很好……我们只剩下从集合中删除域了。但我担心我的孩子AppDomain 真的没装。我想它最终可能会得到gc,但这并没有给我一个温暖的模糊。

    子AppDomain程序集(Windows窗体应用程序)通过继承的适配器类中引用的接口(IModule)异步启动。 MarshalByRefObject . 我想知道对i module的start()(插件模块程序集实现的)的引用是否未正确封送(因为我的实现)。因此,当调用shutdown()方法时,整个应用程序都将终止。我应该将imodule设置为抽象类,这样它也应该继承MBR吗?困惑。。。

    查看我的代码后:

    // 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);
    

    …我担心的是,由于imodule是一个接口,即使我正在子域中创建一个实例,程序集也会泄漏到我的主AppDomain中。因此,当我尝试卸载子域时,两个域都将被卸载。这是正确的吗?通过MBR(适配器)对象提供start()&stop()方法的最佳解决方案是什么?

    更新:有关更改,请参阅下面的答案--
    好吧,没有泄漏——所有东西都继承了MBR:

    1. host:marshalByRefObject--在新AppDomain中实例moduleAdapter
    2. moduleadapter:marshalByRefObject--IModule接口,接口方法(start、stop)
    3. mymodulePlugin:MarshalByRefObject--application.run(myForm)

    我还在做错事吗?我试过几件事,但似乎是错的或是不完整的。当我告诉模块适配器关闭时,它调用 AppDomain.Unload(AppDomain.CurrentDomain) 主机域也会停止。在应用程序退出时,我仍然会收到一些“第一次机会”异常。但窗体(myForm)已被告知.close()。

    所以,我仍然在寻找正确的方法…

    1 回复  |  直到 11 年前
        1
  •  1
  •   mdzindzeleta    16 年前

    正如我所怀疑的,在主域中使用IModule接口实例会导致泄漏。要正确执行此操作:

    AppDomain domain = AppDomain.CreateDomain(domainName);
    HostDomains[domainName] = domain;  // put in collection
    
    ModuleAdapter adapter = (ModuleAdapter)domain.CreateInstanceAndUnwrap(asmName , typeName);
    

    其中moduleadapter继承 MarshalByRefObject .然后:

    adapter.Execute(moduleAssembly , moduleType);
    

    在ModuleAdapter类中:

    public void Execute(string Name, string EntryPoint)
    {
        module  = (IModule)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(Name , EntryPoint);
    }
    

    为了更好的方式,我欢迎评论或其他答案。

    在将实例移动到moduleadapter类之后,我们仍然存在appdomain.unload的问题,它会杀死整个应用程序。我想知道这是否是因为在我们使用的模块插件中 Application.Run(myForm) -然后当我们关闭时,我们调用myform.close()。显然,这会关闭应用程序,因此我想知道myform.close()是否也“卸载”AppDomain。