非静态委托的DoCallBack CrossAppDomainDelegate行为

7
请考虑以下代码片段:
// Create a new application domain
AppDomain ad = AppDomain.CreateDomain("New domain");

Worker work = new Worker();

// if Worker class is marked as 'MarshalByRefObject', this will run in current
// appdomain.
// if Worker class is NOT marked as 'MarshalByRefObject' and is marked as
// 'Serializable', this will run in a new appdomain.
ad.DoCallBack(work.PrintDomain);
// or ad.DoCallBack(new CrossAppDomainDelegate(work.PrintDomain));

// But for static methods:
// If ppp method is static, no marking is required and it will run in
// a new AppDomain.
ad.DoCallBack(Worker.ppp);

我们如何解释DoCallBack的行为呢?

  1. Worker类标记为MarshalByRefObject时,为什么非静态方法PrintDomain在当前域中执行?
  2. Worker类标记为Serializable时,为什么非静态方法PrintDomain在一个新的AppDomain中执行?
  3. 为什么静态方法不需要任何标记?
1个回答

7
当Worker类被标记为MarshalByRefObject时,为什么非静态方法PrintDomain在当前域内执行?
因为这就是MBRO的工作原理,它为您在主应用程序域中创建的对象创建了一个代理。从而将来自辅助应用程序域的调用进行转发到拥有该对象的主应用程序域。
当Worker类被标记为Serializable时,为什么非静态方法PrintDomain在新的AppDomain中执行?
因为这种情况不使用代理。对象本身从主应用程序域传递到辅助应用程序域。这可能是因为您将其标记为[Serializable]。因此,调用在辅助应用程序域中执行。
为什么静态方法不需要任何标记?
不清楚您所说的“标记”是什么意思,但对于静态方法并没有任何不同。一些用于测试的代码,取消基类上的注释以比较这两种情况:
using System;

class Program {
    static void Main(string[] args) {
        var dom = AppDomain.CreateDomain("Test");
        var obj = new WorkerMbro();
        dom.DoCallBack(obj.PrintDomain);
        dom.DoCallBack(obj.PrintDomainStatic);
        Console.ReadLine();
    }
}
[Serializable]
class WorkerMbro /* : MarshalByRefObject */ {
    public void PrintDomain() {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
    }
    public void PrintDomainStatic() {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
    }
}

发布的输出:

Test
Test

输出已删除注释以使用代理:

ConsoleApplication1.vshost.exe
ConsoleApplication1.vshost.exe

1
你的方法 PrintDomainStatic 不是静态的。当代理被使用时(取消注释 MarshalByRefObject),输出为 ConsoleApplication1.vshost.exe Test - Troopers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接