咨询区
-
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.
大佬提供的三种方式很不错,学习了。