2

最近、私は影響を及ぼさない外部の dll ライブラリを使用しました。特殊な状況下では、このサード パーティの dll のメソッドがブロックされ、決して返されません。

新しい AppDomain でこのメソッドを実行して、この問題を回避しようとしました。カスタム タイムアウトの後、私は AppDomain をアンロードして、このがらくたをすべて殺したかった ;)

残念ながら、それは機能しません - 誰かが期待するように。

ブロッキング メソッドではスレッドを正常に中止できないため、しばらくすると CannotUnloadAppDomainException がスローされます。

私はこのライブラリの使用に依存しており、すぐに更新されるとは思われません。

ベスト プラクティスではない場合でも、この問題を回避できますか? どんな悪いハックでも大歓迎です:)

4

3 に答える 3

5

通常、AppDomain はその問題を解決できません。プログラムの状態を破棄するのは良いことです。本当の問題は、スレッドがスタックしていることです。このような場合、 Thread.Abort() の呼び出しは機能しない可能性が高く、スタックするだけです。スレッドは、CLR 同期オブジェクトでブロックされている "アラート可能な待機状態" である場合にのみ中止できます。またはマネージ コードの実行。CLR が安全にクリーンアップする方法を認識している状態。ほとんどのサード パーティ コードは、アンマネージ コードを実行するときにこのように失敗します。これを安全な方法でクリーンアップする方法はありません。これが事実であるという決定的なヒントは、AppDomain.Unload がジョブを完了できないことです。ドメインでコードを実行しているスレッドを中止できる場合にのみ、AppDomain をアンロードできます。

唯一の適切な代替手段は、そのコードを別のプロセスで実行することです。Process.Kill() で殺すことができます。Windows がクリーンアップを行います。そのコードと対話するには、.NET 相互運用メカニズムを使用します。名前付きパイプ、ソケット、リモート処理、または WCF と同様です。さらに、タイムアウトを検出できるコードを作成するというかなりの手間がかかるため、プロセスが強制終了され、プロセスがバックアップされ、内部状態が回復されます。これは、そのサード パーティ コードの初期化されていないインスタンスで再起動するためです。

本当の修正を忘れないでください。問題を再現する小さな再現プロジェクトを作成します。ハングしたら、プロセスのミニダンプを作成します。両方をサードパーティ サポート グループに送信します。

于 2012-10-22T14:36:27.087 に答える
3

これを読んだ後(ブロックの問題までスクロールダウンしてください)、あなたの唯一の解決策は、別のプロセスでメソッドを実行することだと思います-これには、かなりの量のリファクタリングおよび/またはロードする「ホスト」プロジェクト(コンソールアプリケーションなど)が含まれる場合がありますProcessクラスを使用して新しいプロセスを起動するときに、問題のメソッドを簡単に呼び出すことができます (コマンド ラインから引数を読み取るなど)。

于 2012-10-22T14:19:12.433 に答える
1

新しい appdomain を作成する必要はなく、いつでもバックグラウンド ワーカーを使用できます。これにより、スレッドの実行を完全に制御できます。

ただし、スレッドを適切に中止できることを保証する方法はありません。dll は管理されていないため、メモリ リークが発生する可能性があります。ただし、新しいスレッドを生成すると、Dll が応答しないときにアプリケーションがクラッシュしないことが保証されます。

于 2012-10-22T13:45:36.607 に答える