5

私は問題を抱えています。私が開発しているアプリケーションのユーザーの 1 人が、時折、しかし定期的にアプリケーションのハングを経験しています。

これが発生すると、マシンのイベント ログに「アプリケーション ハング」のソースを含むエントリが見つかります。情報メッセージは、「アプリケーション [my app]、バージョン [正しいバージョン] をハングしています。モジュール hangapp、バージョン 0.0.0.0 をハングしています。アドレス 0x00000000 をハングアップします。」

アプリケーションがスローする未処理の例外をすべてログに記録していますが、これが発生してもログ ファイルにはエントリがありません。

私の現在の作業仮説は、アプリケーションが安全でないレガシー API を呼び出しているときに、このハングが発生しているというものです。これは私を驚かせません。私はこの API を何年も使用してきましたが、これまでハングしたことはありませんでしたが、本当にくだらないコードです。また、プログラムがランダムにハングするように見えるというユーザーの報告。これは真実ではないと思います。私が彼女を信じていないわけではありませんが、従来の API と対話するコードは、BackgroundWorker によって呼び出されるメソッド内で実行されています。バックグラウンド スレッドがアプリケーションをハングさせていた場合、これはユーザーにとってランダムに発生しているように見える可能性があります。

では、2 つの質問があります。1 つは具体的なもので、もう 1 つは一般的なものです。

具体的な質問: 非 UI スレッドで実行されているメソッドがハングした場合、スレッドが強制終了されるだけだと思います。それは実際にアプリケーション全体を殺しますか?

一般的な質問:

未処理の例外はすべてログに記録しています。私のプログラムは既にトレースを使用するように設定されています (ただし、疑わしいメソッドのアクティビティをトレースするには、インストルメンテーション コードを追加する必要があります)。他にやるべきことはありますか?.NET アプリケーションがハングしたときにクラッシュ後の分析を可能にする診断ツールはありますか? より多くの (そしてより使いやすい) データを取得するために呼び出すことができる .NET フレームワーク内のメカニズムはありますか?

編集: 私のコードを詳しく調べると、BackgroundWorker の使用はすべて、例外ハンドラーで呼び出されたメソッドをラップする、実装したユーティリティ クラスを介して行われていることを思い出しました。このハンドラーは例外をログに記録し、それをユーティリティ オブジェクトのプロパティとして返します。UI スレッドの完了イベント ハンドラーが例外を再スローし (コール スタックを失ったので、理想的とは言えませんが、既にログに記録されています)、UI のメインの例外ハンドラーが例外をメッセージ ボックスに報告し、終了します。アプリ。

そのようなことは何も起きていないので、バックグラウンド スレッドで例外がスローされることはないと確信しています。とにかく、.NET 例外はありません。

さらなるフォローアップ:

幸いなことに、ユーザーから十分なデータを取得して、レガシー API 内でハングが発生していないことを確認しました。これは、明らかに私が間違っていることを意味します。つまり、私はそれを修正できるので、勝ちます。また、トレースによって問題を切り分けることができることも意味します。これは、もう 1 つのメリットです。この質問に対する回答にとても満足しています。私は、おそらくこの問題にそれらを必要としないことをさらに嬉しく思います.

また、PostSharp は優れています。インストルメンテーション コードを既存のアプリケーションに追加する必要がある場合は、ほぼ確実にそれを使用する必要があります。

4

7 に答える 7

4

特定の質問への回答として、バックグラウンド/ワーカー スレッドがブロックまたはハングした場合、アプリケーションの残りの部分への影響は、アプリ内のスレッド間で発生する同期に大きく依存します。必ずしもアプリ全体がハングする特別な理由はありませんが、ハングする可能性は十分にあります。

これを診断する 1 つの可能な方法は、プロセスがハングしている間にプロセスのダンプを生成することです (プロセスが発生したときに誰かが気付いていると仮定します)。これは、dbghelp.dll の MiniDumpWriteDump を使用して行われます。プロセスを (pid に基づいて) ダンプできる単純なツールを作成するのはかなり簡単で、問題が発生している顧客に提供できます。これはマネージド アプリであるため、フル メモリ ダンプ (MiniDumpWithFullMemory) が推奨されますが、通常のダンプにも有用な情報が含まれているはずです。ダンプを取得したら、windbg または選択した事後分析デバッガーを使用して、何が起こっているのかを確認できます。

この方法を使用する場合、この msdn 記事はマネージ ダンプのデバッグの出発点として適しています。

于 2008-10-14T19:07:49.897 に答える
1

問題の原因であると思われる呼び出しについて、より詳細なログを追加することをお勧めします。

Vista を使用している場合は、新しい Vista API を使用して、アプリがクラッシュしたときに Windows がコードを呼び出すことができます。これは、Office/IE などの MS 製品が「データの回復を試みています」と言っている場合に発生していることです。

于 2008-10-14T19:08:39.693 に答える
0

WinDbg(ええ、それらのハードコアなものの1つ)をアタッチし、SOS(Son Of Strike)とSOSExを使用してデッドロック(!dlk)を分析するか、同期ブロック(!syncblk)を手動でチェックして相互に待機しているロックを見つけることをお勧めします。

于 2008-10-14T21:27:39.723 に答える
0

制御するスレッドに未処理の実行がある場合、アプリケーション全体がダウンします。スレッドが終了すると、これを「処理」する方法はありません。デリゲートで APM を使用する方法を調べたいと思うかもしれません。これにより、EndInvoke() を呼び出したときに例外がキャプチャされて転送されるため、他のスレッドでスローされた例外からの保護層が提供されます。

他に何ができるかについては、チャーリーの答えを支持します。

于 2008-10-14T19:10:05.353 に答える
0

可能であれば、バックグラウンド ワーカー スレッドをSafeThreadに置き換えて、疑わしい例外をキャッチするかどうかを確認してください。そうでない場合、スローされる例外は CLR 例外ではなく、「純粋な」.NET コードからは処理できない可能性があります [ただし、C++ の SEH は機能する可能性があります]。

編集:そうではありません。多分これまたはこれが役立つかもしれません。幸運を!

于 2008-10-14T19:14:07.310 に答える
0

ロバート、これらのソリューションがすべてうまくいかず、レガシー API が原因であると考えている場合、おそらく答えは、レガシー API を独自の AppDomain またはプロセスにサンドボックス化することです。

.NET 3.5 フレームワークでは、System.AddIn API を使用してこれを非常に簡単に行うことができます。

于 2008-10-14T20:28:32.743 に答える
0

1) .net フレームワーク コードに足を踏み入れる (私の職場の KB から):

VS2008 SP1 をインストールした場合は、[ツール] -> [オプション] -> [デバッグ] に移動するだけです。

  1. マイ コードのみを有効にするのチェックを外す
  2. [.NET Framework ソースのステッピングを有効にする] をオンにします。
  3. ソースサーバーのサポートを有効にするにチェックを入れる
  4. [デバッグ] -> [シンボル] の下に、http://referencesource.microsoft.com/symbolsの新しい場所を追加します。

コール スタックでグレイアウトされたフレームワーク コードをデバッグする場合は、コール行を右クリックして [シンボルの読み込み] を選択します。

考え 2) リモート デバッグのセットアップhttp://msdn.microsoft.com/en-us/library/y7f5zaaa.aspx

于 2008-10-14T19:07:47.383 に答える