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?
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.
EDIT: Refer here for more detailed information including a link to an implementation example.
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.
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.
-Oisin
I just discovered that you may also use the AppDomain.SetData but this is only one way From Host Domain to Child Domain.
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 :)
childDomain.SetData("domain", AppDomain.CurrentDomain);
and then perform GetData("domain")
in Child Domain to perform yet another Set/GetData and DoCallBack. –
Kannada CallContext allows passing data between 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.
This is just a quick thought, but I heard that even for cross-domain communication WCF would be the recommended approach, starting from .NET 3.0 of course. Actually this makes sense, as remoting is just another technology wrapped by WCF.
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.
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.
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.
© 2022 - 2024 — McMap. All rights reserved.