AppDomain中的静态字段
我正在尝试使用AppDomain来pipe理一些遗留代码,这些代码在multithreading环境中包含大量的静态字段。
我读这个问题的答案: 如何使用AppDomain限制静态类的线程安全使用的范围? ,认为这是相当有前途的,并决定尝试一个非常简单的类在ClassLibrary1.dll中:
namespace ClassLibrary1 { public static class Class1 { private static int Value = 0; public static void IncrementAndPrint() { Console.WriteLine(Value++); } } }
这里是我的代码加载组装到2个不同的应用程序域,并调用IncrementAndPrint()几次:
var appDomain1 = System.AppDomain.CreateDomain("AppDomain1"); var appDomain2 = System.AppDomain.CreateDomain("AppDomain2"); var assemblyInAppDomain1 = appDomain1.Load("ClassLibrary1"); var assemblyInAppDomain2 = appDomain2.Load("ClassLibrary1"); var class1InAppDomain1 = assemblyInAppDomain1.GetType("ClassLibrary1.Class1"); var class1InAppDomain2 = assemblyInAppDomain2.GetType("ClassLibrary1.Class1"); class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain1.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null); class1InAppDomain2.InvokeMember("IncrementAndPrint", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
我期待的输出是:
0 1 2 0 1 2
因为将存在AppDomain的每个实例的本地静态字段Value的副本。 但是,我得到的是:
0 1 2 3 4 5
这告诉我他们仍然全部共享静态字段Value的相同副本。 谁能告诉我我在这里做错了什么?
更新:
我尝试了Erik的build议,现在我调用AppDomain类的CreateInstanceAndUnwrap()方法,而不是调用Load()和GetType(),如下所示。 另外,我已经将IncrementAndPrint转换为实例方法而不是静态方法。 但是,我仍然得到相同的结果。
var appDomain1 = System.AppDomain.CreateDomain("AppDomain1"); var appDomain2 = System.AppDomain.CreateDomain("AppDomain2"); var class1InAppDomain1 = (Class1)appDomain1.CreateInstanceAndUnwrap("ClassLibrary1", "ClassLibrary1.Class1"); var class1InAppDomain2 = (Class1)appDomain2.CreateInstanceAndUnwrap("ClassLibrary1", "ClassLibrary1.Class1"); class1InAppDomain1.IncrementAndPrint(); class1InAppDomain1.IncrementAndPrint(); class1InAppDomain1.IncrementAndPrint(); class1InAppDomain2.IncrementAndPrint(); class1InAppDomain2.IncrementAndPrint(); class1InAppDomain2.IncrementAndPrint();
它看起来像是从另一个appDomain加载到当前的appDomain的types。 因此调用静态方法的代码是从当前的appDomain调用的。
我不知道任何其他方式调用另一个域中的静态方法,而无需在另一个域中创build一个对象的实例,并让该对象调用静态方法。
示例:解决scheme包含2个项目(ClassLibrary和Winforms / Console应用程序)
[ClassLibrary]
using System; namespace MyLibrary { public class DomainObject : MarshalByRefObject { private static int _Value; private static void IncrementValue() { DomainObject._Value++; } public static int Value { get { return DomainObject._Value; } } public int GetIncrementedValue() { DomainObject.IncrementValue(); return DomainObject.Value; } } }
[应用]
private void button1_Click(object sender, EventArgs e) { AppDomain domain1 = AppDomain.CreateDomain("domain1"); AppDomain domain2 = AppDomain.CreateDomain("domain2"); DomainObject object1 = domain1.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") as DomainObject; DomainObject object2 = domain2.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") as DomainObject; if (object1 != null) { Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); } if (object2 != null) { Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); } /* Unload the Domain and re-create * This should reset the Static Value in the AppDomain */ AppDomain.Unload(domain1); domain1 = AppDomain.CreateDomain("domain1"); object1 = domain1.CreateInstanceAndUnwrap("MyLibrary", "MyLibrary.DomainObject") as DomainObject; if (object1 != null) { Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); Console.WriteLine("object 1 Value = " + object1.GetIncrementedValue().ToString()); } if (object2 != null) { Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); Console.WriteLine("object 2 Value = " + object2.GetIncrementedValue().ToString()); } }
生成的结果:
object 1 Value = 1 object 1 Value = 2 object 1 Value = 3 object 2 Value = 1 object 2 Value = 2 object 2 Value = 3 object 1 Value = 1 object 1 Value = 2 object 1 Value = 3 object 2 Value = 4 object 2 Value = 5 object 2 Value = 6