【问题标题】:DoCallBack CrossAppDomainDelegate behavior for non-static delegates非静态委托的 DoCallBack CrossAppDomainDelegate 行为
【发布时间】:2013-05-11 02:16:10
【问题描述】:

请考虑以下代码:

// 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. 为什么静态方法不需要任何标记?

【问题讨论】:

    标签: c#-4.0 .net-4.0 appdomain applicationdomain


    【解决方案1】:

    当Worker类被标记为MarshalByRefObject时,为什么在当前域中执行非静态方法PrintDomain?

    因为这就是 MBRO 的作用,它会为您在主应用程序域中创建的对象创建一个代理。它将来自辅助 appdomain 的调用编组到拥有该对象的 appdomain,即主 appdomain。

    当Worker类被标记为Serializable时,为什么在新的AppDomain中执行非静态方法PrintDomain?

    因为那个场景使用代理。对象本身从主要应用程序域编组到辅助应用程序域。可能是因为您将其标记为 [Serializable]。因此,该调用在辅助 appdomain 中执行。

    为什么静态方法不需要任何标记?

    不清楚您所说的“标记”是什么意思,但对于静态方法来说并没有什么不同。一些代码可以玩,去掉基类上的注释来比较两个场景:

    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
    

    移除 cmets 后的输出,以便使用代理:

    ConsoleApplication1.vshost.exe
    ConsoleApplication1.vshost.exe
    

    【讨论】:

    • 您的方法PrintDomainStatic 不是静态的。使用代理时(MarshalByRefObject 未注释)输出为ConsoleApplication1.vshost.exe Test
    猜你喜欢
    • 1970-01-01
    • 2014-12-17
    • 2012-04-11
    • 2014-06-09
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多