我有一个可以有多个AppDomain的进程.每个AppDomain都会收集一些统计信息.在指定的时间之后,我想累积这些统计信息并将它们保存到文件中.
一种方法是远程处理,我想避免.
我想到的唯一其他技术是将每个AppDomain的数据保存在一个文件中,并在一段特定时间后,其中一个AppDomain收集所有数据并累积它们.
但如果所有这些都可以在内存中完成,那么这将是理想的,而无需在AppDomains之间序列化信息的成本.有人有主意吗?
Alo*_*aus 28
可以在AppDomains之间共享数据,而无需编组.但这是一种相当黑客的方式.您可以创建一个源数据对象,该对象在所有AppDomain之间通过引用共享.这样,您可以将所有数据放入一个共享对象,而无需编组.听起来太容易了吗?
首先要知道如何在没有编组的情况下在AppDomains之间共享数据.为此,您可以通过Marshal.UnsafeAddrOfPinnedArrayElement获取数据源对象的对象地址.然后将此IntPtr传递给对此感兴趣的所有AppDomain.在目标AppDomain中,您需要将此IntPtr转换回对象引用,该对象引用可以完成JIT :: CastAny,如果从方法返回一个对象并将其指针推送到堆栈上,则完成该操作.
Viola您已经将对象作为AppDomains之间的普通指针共享,并且您获得了InvalidCastExceptions.问题是您必须为所有AppDomains LoaderOptimization.MultiDomain设置,以确保定义共享数据类型的程序集作为AppDomain中性类型加载,该类型在所有AppDomain之间具有相同的方法表指针.
您可以找到一个示例应用程序,它作为WMemoryProfiler的一部分完成此操作.请参阅此链接以获取更详细的说明并下载示例代码的链接.
基本代码是
[LoaderOptimization(LoaderOptimization.MultiDomain)]
static public void Main(string[] args)
{
// To load our assembly appdomain neutral we need to use MultiDomain on our hosting and child domain
// If not we would get different Method tables for the same types which would result in InvalidCastExceptions
// for the same type.
var other = AppDomain.CreateDomain("Test"+i.ToString(), AppDomain.CurrentDomain.Evidence, new AppDomainSetup
{
LoaderOptimization = LoaderOptimization.MultiDomain,
});
// Create gate object in other appdomain
DomainGate gate = (DomainGate)other.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(DomainGate).FullName);
// now lets create some data
CrossDomainData data = new CrossDomainData();
data.Input = Enumerable.Range(0, 10).ToList();
// process it in other AppDomain
DomainGate.Send(gate, data);
// Display result calculated in other AppDomain
Console.WriteLine("Calculation in other AppDomain got: {0}", data.Aggregate);
}
}
Run Code Online (Sandbox Code Playgroud)
Ada*_*lph 15
避免序列化的唯一方法是使用派生自MarshalByRefObject的对象来表示您的数据,但在这种情况下,您仍然需要跨AppDomain边界进行编组的成本.这也可能涉及重构/重写大部分代码.
假设通过引用进行编组不是一个选项,则必须在某个时候进行序列化.这根本无法避免.一种方法是使用Neil Barnwell建议,使用数据库,另一种方法是使用您自己建议的本地文件.
根据您的交付时间表和/或.NET 4.0采用,另一种可能或不可行的方法是使用内存映射文件,请参阅.Net Framework 4.0:使用内存映射文件.