AppDomain卸载杀死Parent AppDomain

发布于 2024-08-22 03:17:50 字数 1939 浏览 2 评论 0原文

我无法弄清楚有关我的 AppDomain.Unload(...) 调用的信息。我有一个详细的解释,其中包含我之前的问题中的代码。事实证明,我执行了几个显然不需要的步骤。但是,我相当确定,当创建 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 的适配器类中引用。我想知道对 IModule 的 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 中。因此,当我尝试卸载子域时,两个域都被卸载。这是正确的吗?提供 Start() & 的最佳解决方案可能是什么?通过 MBR(适配器)对象的 Stop() 方法?

更新:请参阅下面我的答案以了解更改--
好的,没有泄漏 - 一切都继承 MBR:

  1. Host : MarshalByRefObject - 在新的 AppDomain 中实例化 ModuleAdapter
  2. ModuleAdapter : MarshalByRefObject - IModule 接口,接口方法(Start、Stop)
  3. MyModulePlugin : MarshalByRefObject - Application.Run(myForm)

我还是做错了什么吗?我已经尝试了几件事,但它似乎是错误的或不完整的。当我告诉 ModuleAdapter 关闭时,它会调用 AppDomain.Unload(AppDomain.CurrentDomain) ,并且主机域也会停止。我仍然在应用程序退出时遇到一些第一次机会异常。但是表单(myForm)已被告知.Close()。

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

I am having trouble figuring something out about my AppDomain.Unload(...) call. I have a detailed explanation with code from my earlier question. As it turns out, I was performing a couple of steps that apparently, I don't need to. However, I am fairly certain that when an AppDomain is created and then held in a collection:

private static Dictionary<string , AppDomain> HostDomains;

void StartNewDomain(string domainName)
{
    AppDomain domain = AppDomain.CreateDomain(domainName);
    HostDomains[domainName] = domain;
}

...when you are done with it, you must unload it:

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

then remove domain from the collection.

When I unload the domain, however, the entire application is ending. If I remove the unload, all is well...and we are simply left with removing the domain from the collection. But I fear that my child AppDomain is not really unloaded. It may eventually get GC'd I guess, but that doesn't give me a warm fuzzy.

The child AppDomain assembly (a Windows Form application) is started asynchronously via an interface (IModule) that is referenced in my adapter class which inherits MarshalByRefObject. I am wondering if this reference to IModule's Start() (which the plugin module assembly implements) is not marshaling properly (because of my implementation). So, when the Shutdown() method is called, the entire application dies. Should I make my IModule an abstract class instead so it should inherit MBR as well? Puzzled...

After looking at my code:

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

...my fear is that since IModule is an interface, even though I am creating an instance in a child domain, the assembly is leaking into my main AppDomain. Therefore, when I attempt to unload the child domain, both domains are being unloaded. Would this be correct? And what would likely be the best solution to provide Start() & Stop() methods via the MBR (adapter) object?

UPDATE: see my answer below for changes --
Okay, there is no leaking -- everything inherits MBR:

  1. Host : MarshalByRefObject -- instances the ModuleAdapter in a new AppDomain
  2. ModuleAdapter : MarshalByRefObject -- IModule interface, interface methods (Start,Stop)
  3. MyModulePlugin : MarshalByRefObject -- Application.Run(myForm)

Am I doing something wrong still? I've tried several things and it just seems to be wrong or incomplete. When I tell the ModuleAdapter to shutdown, it calls AppDomain.Unload(AppDomain.CurrentDomain) and the Host domain stops as well. I am still getting some first chance exceptions on the application exit. But the form (myForm) has been told to .Close().

So, I am still looking for the correct way of doing this...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

默嘫て 2024-08-29 03:17:50

正如我怀疑的那样,在主域中实例化 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。

As I suspected, instancing with the IModule interface in the primary domain causes a leak. In order to do this properly:

AppDomain domain = AppDomain.CreateDomain(domainName);
HostDomains[domainName] = domain;  // put in collection

ModuleAdapter adapter = (ModuleAdapter)domain.CreateInstanceAndUnwrap(asmName , typeName);

where ModuleAdapter inherits MarshalByRefObject. Then:

adapter.Execute(moduleAssembly , moduleType);

Inside the ModuleAdapter class:

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

I do welcome comments or additional answers for a better way.

After moving the instancing to the ModuleAdapter class, we are still having the issue with AppDomain.Unload killing the entire application. I was wondering if this is because in the module plugin we are using Application.Run(myForm) - then when we shutdown we call myForm.Close(). Obviously this shuts down the application so I was wondering if the myForm.Close() also 'unloads' the AppDomain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文