AppDomains之间如何最好地进行通信?
Posted
技术标签:
【中文标题】AppDomains之间如何最好地进行通信?【英文标题】:How best to communicate between AppDomains? 【发布时间】:2010-09-23 18:39:35 【问题描述】:我有一个应用程序需要在多个 AppDomain 之间发送大量消息。我知道我可以使用远程处理来实现这一点,但我也注意到存在跨域委托。有人看过这种问题吗?
【问题讨论】:
WCF 使用命名管道对我来说似乎是最喜欢的 - 这样我至少可以避免进入网络的必要性。谢谢大家! 想详细说明这项技术吗?例如,与 AppDomains 和 MBRO (MarshalByRefObject) 相比,使用命名管道的性能成本和易用性如何。 我手头没有任何数据,但是使用二进制序列化程序和命名管道使我能够在域之间进行几乎无缝的通信。我想出了一个简单的消息总线,从那以后我就可以简单地忽略这个问题了。 【参考方案1】:我在使用带有命名管道绑定的 WCF 方面取得了很好的成功。使用命名管道不会产生网络流量并使用二进制编码,因此它应该非常快,而不会牺牲在未来扩展场景中的分发能力。
编辑: 请参阅here 了解更多详细信息,包括指向实施示例的链接。
【讨论】:
IPC 允许进程相互通信并同步它们的操作,但不适用于应用程序域通信。如果我错了,请纠正我。【参考方案2】:跨域委托只允许使用零参数的 void 方法,而且它可能不是你想的那样。它只是作为一个简单的回调用于从一个应用程序域到另一个应用程序域的通知目的几乎没有用,例如InitComplete() 之类的方法。
Remoting 是唯一的选择,无论您将其称为 WCF 还是其他任何名称、传递可序列化类型或使用 MBRO 类型 (MarshalByRefObjects)。没有你想的那么难。
-奥辛
【讨论】:
向我远程发送声音 .NET 1.1。进行跨应用域通信有没有更新的替代方案? 远程处理从未消失。它仍然在任何地方使用。 WCF 的现代化来自于跨进程 (IPC) 调用。但对于 appdomains,它一直是远程处理的。您可以将 WCF 与命名管道一起使用,但是嗯。 IMO 远程处理不那么麻烦。 @x0n,[Remoting 是] 一种遗留技术,为了向后兼容现有应用程序而保留,不建议用于新开发。现在应该使用 Windows Communication Foundation (WCF) 开发分布式应用程序。 msdn.microsoft.com/library/72x4h507.aspx @Guillaume 是的,我同意 - 我可能应该更清楚地区分,但那是四年前的事了:D【参考方案3】:我刚刚发现您也可以使用 AppDomain.SetData 但这只是一种方法 从主机域到子域。
static void RunInChildDomain()
AppDomain childDomain = AppDomain.CreateDomain("friendlyName");
string parameterValue = "notmii";
childDomain.SetData("parameter", parameterValue);
childDomain.DoCallBack(PrintName);
static void PrintName()
string Name = Convert.ToString(AppDomain.CurrentDomain.GetData("parameter"));
Console.WriteLine(Name);
您还可以使用 AppDomain.FirstChanceException 事件在子应用程序域和主机应用程序域之间创建异常驱动的通信:)
【讨论】:
我很抱歉重新加热了这样一个老问题,但这不仅仅是从父域到子域的一种方式。您可以像这样使用 SetData:childDomain.SetData("domain", AppDomain.CurrentDomain);
,然后在子域中执行 GetData("domain")
以执行另一个 Set/GetData 和 DoCallBack。【参考方案4】:
CallContext 允许在 AppDomain 之间传递数据:
CallContext.LogicalSetData("Key", "My value");
Console.WriteLine("0 from 1", CallContext.LogicalGetData("Key"),
AppDomain.CurrentDomain.FriendlyName);
var appDomain = AppDomain.CreateDomain("Worker");
appDomain.DoCallBack(() => Console.WriteLine("0 from 1",
CallContext.LogicalGetData("Key"),
AppDomain.CurrentDomain.FriendlyName));
AppDomain.Unload(appDomain);
CallContext.FreeNamedDataSlot("Key");
代码使用 System.Runtime.Remoting.Messaging。我个人没有衡量这个解决方案的性能。
【讨论】:
这适用于任何两个域,而不仅仅是父子域。 +1【参考方案5】:这只是一个快速的想法,但我听说即使对于跨域通信 WCF 也是推荐的方法,当然从 .NET 3.0 开始。实际上这是有道理的,因为远程处理只是 WCF 封装的另一种技术。
【讨论】:
【参考方案6】:我想扩展 xOn 的答案。他建议使用 WCF 或 MarshalByRefObject,但考虑到问题是关于 AppDomain 之间的通信,而不是关于进程之间的通信,我认为 MBRO 方法的实现要简单得多,因此是正确的答案。
当我自己研究这个问题时,起初我很难理解子 AppDomain 如何与父级通信,直到我意识到你可以将一个 MBRO 对象的句柄传递给子级,然后子级就可以展开该句柄与父级(或任何其他 AppDomain)进行通信。我针对自己的问题 here 发布了解决方案。
我随后了解到,您可以定义一个接口,在一个复杂的类上实现该接口,然后只将一个句柄传递给该接口。这可以大大减少加载子 AppDomain 可能需要的程序集数量。
【讨论】:
以上是关于AppDomains之间如何最好地进行通信?的主要内容,如果未能解决你的问题,请参考以下文章
如何最好地在两个 ASP.NET Core 服务器应用程序之间进行通信? [关闭]
如何使用管道/excel最好地构建4个进程之间的进程间通信?
如何在微服务架构中使用 docker-compose 最好地处理共享服务以进行本地开发?