【发布时间】:2011-05-16 23:34:24
【问题描述】:
我正在尝试使用 AppDomain 来管理一些在多线程环境中包含大量静态字段的遗留代码。
我读到了这个问题的答案:How to use an AppDomain to limit a static class' scope for thread-safe use?,认为它很有前途,并决定在程序集 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
这告诉我他们仍然共享静态字段值的相同副本。 谁能告诉我我在这里做错了什么?
更新:
我尝试了 Erik 的建议,现在我调用 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();
【问题讨论】:
-
您正在调用当前应用程序域中的静态方法。您需要创建一个调用 Class1 类上的 Static 方法的 Instance 方法。
-
您好 Erik,如果您查看我更新的源代码,我已将 IncrementAndPrint() 转换为实例方法,并使用 CreateInstanceAndUnWrap() 在各个应用程序域中创建实例。但是,我仍然得到相同的结果
-
我完全忘记在您的 appDomain 模型上提及
MarhsalByRefObject。