C# 如何最好地在 AppDomains 之间进行通信?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/314268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How best to communicate between AppDomains?
提问by open-collar
I have an application that needs to send a moderately high volume of messages between a number of AppDomains. I know that I could implement this using remoting, but I have also noticed that there are cross-domain delegates. Has anyone looked at this kind of problem?
我有一个应用程序需要在多个 AppDomains 之间发送中等数量的消息。我知道我可以使用远程处理来实现这一点,但我也注意到存在跨域委托。有没有人看过这种问题?
采纳答案by Michael Meadows
I have had good success using WCF with a named pipes binding. Using named pipes creates no network traffic and uses binary encoding, so it should be pretty fast without sacrificing the ability to distribute in future scaling scenarios.
我使用带有命名管道绑定的 WCF 取得了很好的成功。使用命名管道不会创建网络流量并使用二进制编码,因此它应该非常快,而不会牺牲在未来扩展场景中分发的能力。
EDIT: Refer herefor more detailed information including a link to an implementation example.
编辑:请参阅此处了解更多详细信息,包括指向实现示例的链接。
回答by lvaneenoo
This is just a quick thought, but I heard that even for cross-domain communication WCFwould be the recommended approach, starting from .NET 3.0 of course. Actually this makes sense, as remoting is just another technology wrapped by WCF.
这只是一个快速的想法,但我听说即使是跨域通信WCF也是推荐的方法,当然从 .NET 3.0 开始。实际上这是有道理的,因为远程处理只是 WCF 封装的另一种技术。
回答by x0n
A cross-domain delegate only allows a void method with zero parameters, and it's probably not what you think it is. It's only barely useful as a simple callback for notification purposes from one appdomain to another, e.g. a method like InitComplete() or something.
跨域委托只允许使用零参数的 void 方法,它可能不是您认为的那样。它只是作为从一个应用程序域到另一个应用程序域的通知目的的简单回调几乎没有用,例如像 InitComplete() 之类的方法或其他东西。
Remoting is the ONLY choice, whether you call it WCF or whatever else, passing serializable types, or using MBRO types (MarshalByRefObjects). It's not as hard as you think.
远程处理是唯一的选择,无论您将其称为 WCF 还是其他任何名称,传递可序列化类型,或使用 MBRO 类型 (MarshalByRefObjects)。这并不像你想象的那么难。
-Oisin
-Oisin
回答by notmii
I just discovered that you may also use the AppDomain.SetData but this is only one way From Host Domain to Child Domain.
我刚刚发现您也可以使用 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);
}
You can also create exception driven communication between child and host appdomain by using AppDomain.FirstChanceException event :)
您还可以使用 AppDomain.FirstChanceException 事件在子应用程序域和主机应用程序域之间创建异常驱动的通信:)
回答by Bert Cushman
I want to expand on xOn's answer. He recommends using either WCF or MarshalByRefObject, but given that the question asks about communication between AppDomains, and not about communication between processes, I think the MBRO approach is significantly simpler to implement, and is therefore the right answer.
我想扩展 xOn 的答案。他建议使用 WCF 或 MarshalByRefObject,但鉴于问题询问的是 AppDomains 之间的通信,而不是进程之间的通信,我认为 MBRO 方法实施起来要简单得多,因此是正确的答案。
When I was researching this issue myself, I struggled at first to understand how the child AppDomain could communicate with the parent, until I realized that you could pass a handle to a MBRO object into the child, and the child could then unwrap that handle to communicate back to the parent (or any other AppDomain). I posted a solution to my own question here.
当我自己研究这个问题时,我一开始很难理解子 AppDomain 如何与父级通信,直到我意识到你可以将一个 MBRO 对象的句柄传递给子级,然后子级可以解开该句柄到与父级(或任何其他 AppDomain)通信。我在这里发布了我自己问题的解决方案。
I subsequently learned that you can define an interface, implement that interface on a complex class, and then pass a handle to only the interface. This can greatly reduce the number of assemblies that might be required to load the child AppDomain.
我随后了解到您可以定义一个接口,在一个复杂的类上实现该接口,然后只将一个句柄传递给该接口。这可以大大减少加载子 AppDomain 可能需要的程序集数量。
回答by Vadim S.
CallContext allows passing data between AppDomains:
CallContext 允许在 AppDomains 之间传递数据:
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");
The code uses System.Runtime.Remoting.Messaging. I personally didn't measure the performance of this solution.
该代码使用 System.Runtime.Remoting.Messaging。我个人没有衡量这个解决方案的性能。