Appdomainの問題

私はappdomainの問題を把握しようとしている最後の数日間、壁に頭を打っている。 私はプラグインを実行する小さなウィンドウサービスを作成しました。それが動作する方法は、各プラグインは、 "CreateInstanceAndUnwrap"を使用して独自の別個のappdomainにロードされるdllであり、appdomainへの参照を保持し、プラグインが完了すると、そのplugin.i用に作成されたappdomainをシ​​ャットダウンしますシャドウコピーを使用して、プラグインがフレームワークで実行されている間にプラグインを更新できるようにしています。私はフレームワークのコア機能を別個のDLLに入れ、別のappdomainでそのDLLを実行することに決めたとき、6ヶ月間完全に実行されました。今のところ動作しています:

Windowsサービスが起動します。コアdllは、CreateInstanceAndUnwrapを使用してロードされ、実行されます。これは、独自の別個のappdomainsでプラグインを実行することになります (CreateInstanceandを使用して..)

私はアセンブリのためにいくつかの異なる場所があります: Bin Folder(WindowsサービスのBinには、サービスで使用されているDLLのみが保持されます) コアDLLフォルダ(コアdllはここにドロップされます) 参照フォルダ(任意の参照はここにドロップされます) プラグインフォルダ(プラグインはここにドロップされます)

のappdomainのonassemblyresolveハンドラに接続することによって、未確認のDLLを解決します。 つまり、dllはネットワーク経由でロードされる可能性があります。

今問題は、Windowsサービスが1日実行され、メモリが1.5Gの高さになったことです。 私はメモリのダンプを作成し、ロードされたモジュールは、1.5G全体の100MBしかないように思われるので、このメモリがどこに行くのか分かりません。 debugdiagの使用ヒープフラグメンテーションの警告が表示されましたが、どこで問題を診断するか分かりません。 通常、フレームワークが1日実行されると、100Mのようなものが消費されました。また、これはプラグインとは関係がありません。これは、以前のようにmemroyの使用法がノーマルになったフレームワークに変更をロールバックしたときのようなものです。 私はプラグインのためのappdomainsを作成するとき、私はアセンブリの解決があまり頻繁に呼ばれることを望んでそこにdllの大部分を持っているCOREとReferencesフォルダへのappdomainのbasePathとbinパスを切り替えます。

私はfusionログを見て、default、from、noneのようなロードコンテキストについてもう少し詳しく読んだが、正しいパスが取れているかどうかわからなかった。

何か案は?

2
私は2番目のappdomainのプロキシを取得するためにインターフェイスを使用し、最近バグは有名な "タイプキャスト無効なキャスト"のためにキャストしていたので、代わりにダイナミックタイプにリターンキャストを切り替えた:これは問題の良い解決策ではありませんが、キャスティングの問題を解決しました。インターフェイスdllの複数のバージョンが呼び出しappdomainにロードされていると推測しています。なぜ型キャストexception.iを与えているのですか?また、プラグインのappdomainsを使用してcreateinstanceandunwrap.for解決asselmblyイベント私は "LoadFrom"
追加された 著者 James,

1 答え

私はこれを考える:

フレームワークのコア機能を   別のDLLをまた、別のappdomainでそのDLLを実行します。   今のところうまくいきます:

     

Windowsサービスが起動します。コアdllは、   CreateInstanceAndUnwrapは順番に実行します。   独自の別個のappdomains(CreateInstanceand ..を使って)のプラグイン

これに反しているかもしれません:

From http://msdn.microsoft.com/en-us/library/3c4f1xde.aspx

タイプT1のオブジェクトのメソッドMに事前バインドされた呼び出しを行うと   そのメソッドはCreateInstanceAndUnwrapによって返され、そのメソッドは   アセンブリCの型T2のオブジェクトのメソッドへの初期バインド呼び出し   現在のアセンブリまたはT1を含むアセンブリ以外の、   アセンブリCが現在のアプリケーションドメインにロードされます。このローディング   T1.M()への初期バインドされた呼び出しが   DynamicMethod、またはその他の動的に生成されたコードで使用されます。もし   現在のドメインは既定のドメインです。アセンブリCはアンロードできません   プロセスが終了するまで。

この場合、Reflectionを使用して「適切な」呼び出しを実行して、早期バインディングを排除することができます。

1
追加された
リフレクションは、動的に生成されないコードを呼び出すために使用できます。たとえば、Reflection MethodInfoを使用すると、動的コードは生成されず、コンパイル時に定義されたメソッドを呼び出すために使用できます。だから私はまだ早期の拘束力を破る可能性があると思う。
追加された 著者 Nathan,
間違いなくパズル。 stackoverflow.com/questions/2634858/… のようになりますが、これは少し異なるケースです(ダイナミックキーワードをどこでも使用しているとは思わない)。しかし、それは反射にいくつかの追加のメタデータを提供することについてのいくつかのヒントを提供するかもしれません - 正に、反射のこの特定の側面にもかかわらず、私は経験の領域から少しを得ています。
追加された 著者 Nathan,
あなたがまだ問題を解決することができないと言うとき、あなたはまだ、反射を働かせることができないという点で話していますか?または、あなたは反射を働かせることができましたが、それはメモリの問題を解決しませんでしたか?
追加された 著者 Nathan,
もう1つの可能な修正は、あなたがリフレクションで呼び出すプロキシ呼び出しをコンパイル時のクラス内でラップし、代わりにリフレクションによってラップされた(コンパイル時の)メソッドを呼び出すことで、MarshalByRefオブジェクトに直接反映されません。
追加された 著者 Nathan,
私はこれが何が起きているかさらに調べるつもりですが、Windowsサービスをデバッグしたときに、重複したDLLがロードされていないか、メインのappdomainにプラグインのDLLがロードされていないことがわかりました。私は1.5Gランニングサービスをダンプしたとしても、debugdiagはその兆候を見せなかった。ロードされたモジュール= 100M!
追加された 著者 James,
また、 "この読み込みは、DynamicMethodの本体や他の動的に生成されたcodで、T1.M()への初期バインドされた呼び出しが行われたとしても発生します。"これは、反射を使用するとおそらくどちらもうまく動作しないことを意味します(これが当てはまる場合)
追加された 著者 James,
私はこれを試みたが、GetMethodは動的に生成されたプロキシで動作していないようです。私は "メソッドはsystem.marshalByRef上に存在しません"例外を取得しています。
追加された 著者 James,
私の場合はメモリの問題の原因になっているようですが、プラグインのいくつかが最初のappdomainに実際にロードされていることがわかりました。 (しかし、彼らは1.5Gを取ってはいけませんので、まだわかりません)
追加された 著者 James,
うん、私はまだ問題を解決することができません:(任意のアイデア?
追加された 著者 James,
私は反射を働かせることができませんでしたが、私はあなたが言及した他のアプローチを試みます。
追加された 著者 James,