1

私は C# の初心者で、AppDomain に関する C# の教科書を勉強していました。

これは、教科書「C# 4.0 in a Nutshell 4e (O'Reilly)」で見つけたものです。

最も基本的なマルチドメイン シナリオをもう一度見てみましょう。

static void Main()
{
    AppDomain newDomain = AppDomain.CreateDomain ("New Domain");
    newDomain.ExecuteAssembly ("test.exe");
    AppDomain.Unload (newDomain);
}

別のドメインで ExecuteAssembly を呼び出すのは便利ですが、ドメインと対話する機会はほとんどありません。また、ターゲット アセンブリが実行可能である必要があり、呼び出し元を単一のエントリ ポイントにコミットします。柔軟性を組み込む唯一の方法は、引数の文字列を実行可能ファイルに渡すなどの方法に頼ることです。
強力なアプローチは、AppDomain の DoCallBack メソッドを使用することです。これは、特定の型のメソッドである別のアプリケーション ドメインで実行されます。型のアセンブリは自動的にドメインに読み込まれます (現在のドメインがそれを参照できる場合、CLR はそれが存在する場所を認識します)。次の例では、現在実行中のクラスのメソッドが新しいドメインで実行されます。

class Program
{
    static void Main()
    {
        AppDomain newDomain = AppDomain.CreateDomain ("New Domain");
        newDomain.DoCallBack (new CrossAppDomainDelegate (SayHello));
        AppDomain.Unload (newDomain);
    }
    static void SayHello()
    {
        Console.WriteLine ("Hi from " + AppDomain.CurrentDomain.FriendlyName);
    }
}

ここで、同じ Program クラスに SayHello() メソッドが存在します。発言により、

「型のアセンブリは自動的にドメインに読み込まれます (現在のドメインがそれを参照できる場合、CLR はそれが存在する場所を認識します)。」

これは、SayHello() メソッドが他のサードパーティ アセンブリに存在する場合、そのアセンブリも読み込まれることを意味しますか? 私はこの声明を理解していませんでした。これで私を助けてもらえますか?ありがとうございました。

4

2 に答える 2

2

しかし、ドメインとやり取りする機会はほとんどありません

それが AppDomain の要点です。アセンブリとデータを分離する機能が存在する理由です。すべての AppDomain には、別の AppDomain のコードやデータとは関係なく、独自のガベージ コレクション ヒープとジャストインタイム コンパイル コードがあります。これは、別のプロセスでコードを実行するための代替手段であり、Windows でプロセス境界を越えることは困難で費用がかかるため、はるかにパフォーマンスの高い代替手段です。

これは、SQL Server と ASP.NET が代表的な例であるサーバー シナリオで利用されます。クライアントからのサービス要求を受け入れ、1 つのプロセスで実行します。分離により、サービス プロセスの存続が非常に強力に保証されます。なんらかの理由でコードが爆発した場合、サーバーは「申し訳ありませんが、機能しませんでした」という応答を返すことができます。そして、サービス リクエスト スレッドを終了し、AppDomain をアンロードして、信頼できなくなったプログラムの状態を破棄することで、未処理の例外から回復します。サーバーは何事もなかったかのようにハミングし続けます。

既定の CLR ホストでは、AppDomains の実用的な用途はほとんどありませんが、アセンブリをアンロードする機能が 1 つあります。これにより、プラグイン スタイルのフレームワークを実装し、オンデマンドでコードをロードおよびアンロードできます。それ以外の場合、アセンブリのアンロードは不可能です。これにより、ジャストインタイムで生成されたマシン コードがクラッシュを引き起こす可能性のある方法が多すぎます。AppDomain 内で生成すると、そのコードを破棄できるため、アセンブリのアンロードが可能になります。

もちろん代償として、2 つの AppDomain 間でデータを交換するのは面倒です。データをある GC ヒープから別の GC ヒープにコピーする必要があります。.NET は、Remoting のおかげで十分にサポートしています。ただし、データ自体は、[Serializable] であるため、値によってマーシャリングされるか、または MarshalByRefObject から派生することによって、プロキシできるため、分割を越えてコピーできる必要があります。

AppDomain.Load() を使用して AppDomain にアセンブリを読み込み、Assembly.CreateInstance() を使用して AppDomain にオブジェクトを作成することにより、ExecuteAssembly() の基本的な例をさらに向上させることができます。これは、.NET でプラグインをサポートする方法に関する Google のヒット記事でよく取り上げられています。

于 2013-02-22T14:54:13.493 に答える
0

これは、SayHello() メソッドが他のサードパーティ アセンブリに存在する場合、そのアセンブリも読み込まれることを意味しますか?

いいえ、そうではありません。前の文をテキストから切り離すと、より理解しやすくなります。

これは、特定の型のメソッドである別のアプリケーション ドメインで実行されます。

あなたの例では、メソッドはSayHelloで、タイプはProgramです。

型のアセンブリは自動的にドメインに読み込まれます

型が定義されているアセンブリは、新しいアプリケーション ドメインに読み込まれます。Programこれは、クラスを含むプロジェクトから構築されるアセンブリです。

(現在のドメインがそれを参照できる場合、CLR はそれがどこにあるかを認識します)。

このアセンブリは既にメイン アプリケーション ドメインに読み込まれているため、CLR はこのアセンブリの場所を認識しています。読み込まれたすべての型について、それらを含むアセンブリの場所を見つけるのは簡単です。この本の前の章で、次のようなコードを見てきました。

Assembly a = typeof(Program).Assembly;

また

Assembly a = anObject.GetType().Assembly;

オブジェクトを取得したらAssembly、プロパティにアクセスLocationし、ロードされたアセンブリへのフルパスを取得できます。

つまり、このステートメントが意味することは、コールバック メソッドの型を含むアセンブリが新しいアプリケーション ドメインに自動的に読み込まれるということです。したがって、このメソッドは、 new 内の任意のアセンブリからコードを実行する場合に便利ですAppDomain。欠点は、後でできることがあまりないことです。Hans が言及しているAppDomainようなある種の AppDomain 間通信を使用しない限り、新しいオブジェクトと通信することはできません。.NET RemotingWCF

于 2013-02-22T17:50:12.877 に答える