.NET(C#):AppDomain.DoCallBack方法和Lambda運算式

來源:互聯網
上載者:User

眾所周知:AppDomain.DoCallBack方法會在指定應用程式定義域中執行代碼,如果傳入委託是靜態,那麼委託正常進行。如果傳入委託是對象的成員函數,那麼這個對象會被封送(按值或者按引用)。

當傳入委託是以Lambda運算式的形式,那麼有些地方值得注意。

如果是傳入對外部變數捕獲的Lambda運算式,那麼DoCallBack方法總會拋出異常的,看下面代碼(這是一種錯誤的在另外一個應用程式定義域中建立Remoting對象的方法)

using System;

using System.Runtime.Remoting;

 

namespace Mgen.TTC

{

    class a : MarshalByRefObject

    { }

 

    class Program

    {

        static void Main()

        {

            var appdom = AppDomain.CreateDomain("new");

            a obj = null;

            appdom.DoCallBack(() =>

                {

                    obj = new a();

                });

            Console.WriteLine(RemotingServices.IsTransparentProxy(obj));

        }

    }

}

 

事實上,程式不僅不會像表面上看的在新的應用程式定義域中建立一個a的對象,而是會拋出異常:

Unhandled Exception: System.Runtime.Serialization.SerializationException: Type '

Mgen.TTC.Program+<>c__DisplayClass1' in assembly 'Mgen, Version=1.0.0.0, Culture

=neutral, PublicKeyToken=null' is not marked as serializable.

   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)

 

由於用到了對外部變數進行捕獲的Lambda運算式,所以這個Lambda會被編譯成一個嵌套在Program類的子類,然後主函數中的本地變數obj會被替換成嵌套類的一個欄位,整個Lambda的執行是嵌套類的一個普通方法。

下面是Reflector下看這個嵌套類:

[CompilerGenerated]

private sealed class <>c__DisplayClass1

{

    // Fields

    public a obj;

 

    // Methods

    public <>c__DisplayClass1()

    {

        base..ctor();

        return;

    }

 

    public void <Main>b__0()

    {

        this.obj = new a();

        return;

    }

}

 

這樣的話:其實a的對象還是在本地應用程式定義域中被建立的。同時傳入DoCallBack的委託是Lambda由編譯器產生的嵌套類的方法。所以由於這個編譯器產生的嵌套類無法被按引用封送或者按值封送而由異常拋出。

 

當然不是所有Lambda運算式都會被編譯成嵌套類,沒有外部變數捕獲的Lambda會被直接編譯成靜態方法!

比如下面代碼(為了更好說明,在非靜態成員函數中生命Lambda)

class b

{

    public void doo()

    {

        var appdom = AppDomain.CreateDomain("new");

        appdom.DoCallBack(() => Console.WriteLine("hehe"));

    }

}

 

class Program

{

    static void Main()

    {

        new b().doo();

    }

}

程式會順利執行(在另一個應用程式定義域中執行Console.WriteLine)。

 

Reflector下b類的源碼

internal class b

{

    // Fields

    [CompilerGenerated]

    private static CrossAppDomainDelegate CS$<>9__CachedAnonymousMethodDelegate1;

 

    // Methods

    public b()

    {

        base..ctor();

        return;

    }

 

    [CompilerGenerated]

    private static void <doo>b__0()

    {

        Console.WriteLine("new引用");

        return;

    }

 

    public void doo()

    {

        AppDomain appdom;

        if (CS$<>9__CachedAnonymousMethodDelegate1 != null)

        {

            goto Label_0024;

        }

        CS$<>9__CachedAnonymousMethodDelegate1 = new CrossAppDomainDelegate(b.<doo>b__0);

    Label_0024:

        AppDomain.CreateDomain("new").DoCallBack(CS$<>9__CachedAnonymousMethodDelegate1);

        return;

    }

}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.