我有一个应用程序需要在多个 AppDomain 之间发送大量消息。我知道我可以使用远程处理来实现这一点,但我也注意到存在跨域委托。有没有人看过这种问题?
6 回答
我在使用带有命名管道绑定的 WCF 方面取得了很好的成功。使用命名管道不会产生网络流量并使用二进制编码,因此它应该非常快,而不会牺牲在未来扩展场景中的分发能力。
编辑:请参阅此处以获取更多详细信息,包括指向实施示例的链接。
跨域委托只允许使用零参数的 void 方法,而且它可能不是你想象的那样。它只是作为一个简单的回调用于从一个应用程序域到另一个应用程序域的通知目的几乎没有用,例如像 InitComplete() 这样的方法或其他方法。
远程处理是唯一的选择,无论您将其称为 WCF 还是其他任何名称、传递可序列化类型或使用 MBRO 类型 (MarshalByRefObjects)。这并不像你想象的那么难。
-Oisin
我刚刚发现您也可以使用 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 事件在子应用程序域和主机应用程序域之间创建异常驱动的通信 :)
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。我个人没有衡量这个解决方案的性能。
这只是一个快速的想法,但我听说即使对于跨域通信WCF也是推荐的方法,当然从 .NET 3.0 开始。实际上这是有道理的,因为远程处理只是 WCF 包装的另一种技术。
我想扩展 xOn 的答案。他建议使用 WCF 或 MarshalByRefObject,但考虑到问题是关于 AppDomain 之间的通信,而不是关于进程之间的通信,我认为 MBRO 方法的实现要简单得多,因此是正确的答案。
当我自己研究这个问题时,我一开始很难理解子 AppDomain 如何与父级通信,直到我意识到你可以将一个 MBRO 对象的句柄传递给子级,然后子级可以打开该句柄到与父级(或任何其他 AppDomain)进行通信。我在这里发布了我自己的问题的解决方案。
后来我了解到,您可以定义一个接口,在一个复杂的类上实现该接口,然后只将一个句柄传递给该接口。这可以大大减少加载子 AppDomain 可能需要的程序集数量。