咨询区
-
open-collar
我有一个程序,需要在多个 AppDomains 之间传递大量的数据,我知道可以使用 Remoting 或者 命名管道 的方式,但个人感觉用在我这个场景下还是太重了,请问是否有轻量级的实现方案?.
回答区
-
V. S.
要想实现 AppDomains 之间的数据传送,实现的方式比较多,总结下来有如下几种:
1. CallContext
用 CallContext 相对轻量级,参考如下代码:
public static void Main()
{
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");
Console.ReadLine();
}
2. AppDomain.SetData
如果你的业务特点只是实现 Host Domain 与 Child Domain 之间的通讯,而不是 Child Domain 到 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);
}
3. 使用 MarshalByRefObject
实现方式是这样的,首先你需要创建一个继承于 MarshalByRefObject 的子类,然后在子类中就能获取到 ObjectHandle,最后通过 ObjectHandle 实现 AppDomain 之间的通讯,参考代码如下:
class Program
{
public class ParentFacade : MarshalByRefObject
{
public List<string> Collection { get; set; }
public void AddElement(string el)
{
Collection.Add(el);
}
}
public class ChildFacade : MarshalByRefObject
{
public void AlterParentState(ObjectHandle handle)
{
var parent = handle.Unwrap() as ParentFacade;
parent.AddElement("Message from child");
}
}
static void Main(string[] args)
{
var child = AppDomain.CreateDomain("child");
var childFacadeType = typeof(ChildFacade);
var childProxy = child.CreateInstanceAndUnwrap(childFacadeType.Assembly.FullName, childFacadeType.FullName) as ChildFacade;
var parentColl = new List<string>();
var facade = new ParentFacade();
facade.Collection = parentColl;
var facadeHandle = new ObjectHandle(facade);
childProxy.AlterParentState(facadeHandle);
foreach (var item in parentColl)
Console.WriteLine(item);
}
}
点评区
有太多方式可以实现 跨进程, 跨机器 通讯,但放在 AppDomain 级别那就太重了,V. S. 大佬提供的三种方式很不错,学习了。