Environment: .NET程序包含多个托管本机代码的dll /程序集 . 程序执行的第一个操作是在命名空间(比如namespaceA)中创建一个继承自MarshalByRefObject的类(比如classA)的实例 .
作为classA构造函数的一部分完成的操作:
-
分配新类(比如classB) . classB包含静态变量 .
-
创建线程 . 通过调用'WinBase''CreateThread'函数,在本机代码的上下文中完成线程的实际创建 .
Problem: 在appDomain的上下文中定义classA的实例时,classB静态变量并不是所有线程都通用的 .
用于加载程序dll并在appDomain中创建classA实例的代码:
System.AppDomain app_domain = System.AppDomain.CreateDomain("app domain");
object winfw_host = app_domain.CreateInstanceFromAndUnwrap(@"C:\...\dll_name.dll", "namespaceA.classA");
Note: 在不在appDomain的上下文中定义classA的实例时,classB静态变量对所有线程都是通用的 .
Question:
我本来期望相同的行为(AppDomain和非AppDomain上下文),区别的原因是什么?
在appDomain的上下文中运行时,是否可以对所有线程强制执行一个常见的静态变量实例?
2 回答
静态变量的范围正是包含AppDomain . 为了恢复这个限制,我建议使用一些棘手的方法 .
您选择一个AppDomain(让我们说A) . AppDomain类公开以下非静态方法 .
尝试通过A.SetData(“你的密钥”,值)存储所有AppDomain共享的值,并通过A.GetData检索值(“你的密钥”)
访问AppDomain A时,您还需要考虑线程安全访问 .
Microsoft批准这是一种预期的行为,当在appDomian上下文中创建多线程时,静态变量并不适用于所有线程(与非appDomain不同,所有线程都有一个静态变量),而且它是C / CLI的实现方式 . 为了实现这种要求,建议创建一个委托类型来包装托管方法调用,以便将它传递给本机代码到本机线程,因为委托在本机线程中保留该AppDomain信息 . 基本上,您创建托管委托,为委托分配GCHandle以在您的本机C代码中引用它,然后在GCHandle上调用Marshal :: GetFunctionPointerForDelegate以获取指向委托的本机函数指针 . 最后一部分需要将IntPtr静态转换为您的本机函数类型 . 然后,您可以传递跨线程获得的本机函数指针 .