3

DLL をプラグインとしてロードする C# (FFx 3.5) アプリケーションがあります。これらのプラグインは個別の AppDomains に読み込まれます (多くの正当な理由により、このアーキテクチャは変更できません)。これはすべて順調です。

これらのプラグインのいずれかからダイアログを表示する必要があります。ダイアログ フォームをメイン アプリケーションに戻してそこに表示することはできないことに注意してください (現在のインフラストラクチャではサポートされていません)。

失敗1

DLL でフォームを作成し、Show を呼び出しました。ダイアログのアウトラインは表示されましたが、描画されず、マウス イベントに応答しません。これは、DLL が別の AppDomain にあり、アプリのメッセージ ポンプがメッセージを新しいフォームにディスパッチできないためであると想定しました。

失敗 2

私の DLL では、フォームを作成し、ShowDialog を呼び出しました。これは、すべての権利により、ダイアログ用の内部メッセージ ポンプを作成する必要があります。ペイントを終了し、マウス イベントに応答しなくなるため、Windows メッセージをディスパッチします。何らかの理由で、メイン アプリのメッセージ ポンプがディスパッチされていないようです。

失敗 3

DLL でフォームを作成し、Application.Run を呼び出しました。これにより、完全な 2 番目のメッセージ ポンプが確実に作成されます。失敗 2 と同じ動作になります。ダイアログは動作しますが、呼び出し元のアプリは動作しません。

ここで正確に何が起こっているのか、他の AppDomain の DLL からダイアログを表示して、呼び出し元と呼び出し先の両方が応答して適切にペイントする方法についての考えはありますか?

4

3 に答える 3

4

appdomain2のフォームを表示するデリゲートでappdomain1のメインフォームのBeginInvokeを使用してみてください。したがって、擬似コードでは:

Appdomain1:
    AppDomain2.DoSomething(myMainForm);

AppDomain2:
    DoSomething(Form parent)
    {
        Form foolishForm = new Form();
        parent.BeginInvoke(new Action( delegate { foolishForm.Show(); } ));
    }

コードは完全ではないかもしれませんが、それは概念を示しています。

ちなみに、リモーティングが原因でフォームの受け渡しに問題がある場合は、次のことができます。

public class Container<T> : MarshalByRefObject
{
    private T _value;
    public T Value { get { return _value; } set { _value = value; } }

    public Container() { }
    public Container(T value) { Value = value; }

    public static implicit operator T(Container<T> container)
    {
        return container.Value;
    }
}

それはあなたがそれに投げるオブジェクトを含みます。

于 2009-01-14T08:49:03.683 に答える
1

DLLファイルとプラグインをロードする非常によく似た設計のアプリケーションがあります。各DLLファイルは、個別のスレッドで作成された個別のアプリケーションドメインにロードされます。System.Windows.Forms.Application.DoEvents()定期的に電話をかけないと表示されない形式のサードパーティによる管理があります。

擬似コード:

<In new thread>
  <Application domain created. Start called inside new application domain.>
  <Start loads new DLL file, calls init function in DLL file>
  <Start loops, calling DoEvents until the DLL file exits>
  <Application domain unloaded>
<Thread exits>

これにより、GUIの問題がすべて解決されました。

于 2009-04-19T12:29:05.027 に答える
1

以前に使用したことの 1 つは、DomainManagerの実装です。さまざまなアプリケーション ドメインのセキュリティ/バインディング/コンテキストをカスタマイズして、必要な場所にデータをポンピングすることに関して、複雑な問題や鶏卵タイプの問題を処理することができます ;)

私は通常、native.exe からこれを行い、COM インターフェイスを介して CLR をブートストラップします (疑似コードですが、順序とメソッド名は正しいです ;):

CorBindToRuntimeEx()
SetHostControl()
GetCLRControl()
SetAppDomainManagerType("yourdomainmanger","info")
// Domain manager set before starting runtime
Start()
HostControl -- GetDomainManagerForDefaultDomain()
DomainManager -- Run()

ドメイン マネージャーは任意のCLRクラス ライブラリである可能性があるため、それほどネイティブな C ではありません。

WPFを使用している場合の注意事項。「Microsoft.DwayneNeed.Controls」メソッドを使用するのが本当に好きです。同じUI コントロール内に独自の Dispatcher ポンプを持つ分散スレッドがある場合(完全に新しい Window() に頼る必要はありません)。

このアプローチを使用することのユニークな点は、プライマリ UI スレッドがブロックされている/ビジーであっても (重い操作、ファイルシステムのスキャンなど)、これらの他のスレッドが問題なく UIElement をペイント/更新できることです。

于 2009-05-29T06:23:15.217 に答える