8

非常に複雑な XAML を使用する WPF アプリケーションがあります。実行を一時停止しようとすると、アプリケーションがハングしているポイントを知る方法が必要です。アプリケーションはハングしていないように見えます。ポインターは次の行にあります。

System.Windows.Application myApp;
.
.
.
.
myApp.Run(); // <== this line

これは、タスク バーのレイアウトを変更したとき、または Windows エクスプローラーがクラッシュしたとき (タスク バーが非表示になったとき) に発生します。これらの変更を頻繁に繰り返すと、アプリケーションは決して回復しませんが、小さな変更を行うと、アプリケーションは数分後に回復します。この問題の原因を知る必要があります。アプリケーションの複雑な XAML には疑問がありますが、ページやコンポーネント、またはこのハングの原因を知る方法が必要です。

* 編集 *

ディスパッチャーの時間を消費する XAML を知るツールまたは方法が必要です。

* 編集 *

ハングの正確な理由がわかりました. 別のスレッドで ReportViewer のインスタンスを作成したためです. インスタンスの作成を削除したとき. 完全に機能しました. 奇妙なことに, この間違いは私のアプリケーションに長い間存在していました以前ですが、最近ハングが発生しました。つまり、アプリケーションの任意の場所に次のコードのいずれかを挿入すると、アプリケーションがハングします。

        new Action(() =>
        {
            ReportViewer rv = new ReportViewer();
        }).BeginInvoke(null, null);

また

        new Action(() =>
        {
            ReportViewer rv = new ReportViewer();
            rv.Dispose();
        }).BeginInvoke(null, null);

また

        new Action(() =>
        {
            ReportViewer rv = new ReportViewer();
            rv.LocalReport.ReleaseSandboxAppDomain();
            rv.Dispose();
        }).BeginInvoke(null, null);

私の質問:

1- ウィンドウのレイアウトの変更 (タスク バーのサイズ変更または移動) と、どのビジュアル ツリーにも追加されていないレポート ビューアーとの関係は何ですか? これによりアプリケーションがハングするのはなぜですか??

2-ハングの場所を特定するにはどうすればよいですか?

3- アプリケーションが数分で回復する場合 (3-5) もありますが、何時間もハングしたままアプリケーションが回復しない場合もあります。なぜですか?

4- この状況でアプリケーションがハングする原因となったコンポーネントまたは構成を特定するにはどうすればよいですか?

ところで、これが解決されれば、他のユーザーにとって非常に便利です。これを検出するために非常に多くの時間を費やしましたが、ハングの原因となった ReportViewer と組み合わせた正確な理由はわかりませんでした。

4

4 に答える 4

9

私はできる限り完全にあなたの質問に答えようとします:

ReportViewer コントロールは Windows フォーム コントロールであり、Windows フォームには適切な状況で UI スレッドがロックされ、アプリケーションがハングする問題があります。

Windows によって WM_SETTINGCHANGED メッセージがポストされると、イベントSystem.Win32.SystemEvents.UserPreferenceChangedが発生します。ReportViewerこのイベントをリッスンするなど、一部の Windows フォーム コントロールは、システム設定が変更されたときに自身を更新します。

このUserPreferenceChangedイベントは、他の通常のイベントとは対照的に、サブスクライブしているスレッドの SynchronzationContext を使用して各ハンドラーを呼び出します。そのため、ReportViewer がメイン UI スレッド (WPF の Dispatcher スレッド) 以外のスレッドで作成された場合、イベント起動コードは呼び出しを実行しようとし、呼び出しが完了するのを待ちますが、これは他のスレッドでは決して起こらないため、UI がフリーズします。 .

ハングの場所を特定するには、Visual Studio で [マイ コードのみを有効にする] -> [ツール] -> [オプション] -> [デバッグ] のオプションを簡単に無効にすることができます。 WaitOne 呼び出しの UserPreferenceChanged イベント処理内でハングします。

このハングの詳細については、次の記事を参照してください。

http://www.ikriv.com/dev/dotnet/MysteriousHang.html

別のスレッドから show を呼び出した後に Windows Forms フォームがハングする

于 2013-01-12T12:47:36.313 に答える
2

簡単 - 別のスレッドで ReportViewer を作成しないでください。1 つの UI 階層に関連付けられているすべての要素は、UI スレッドから取得する必要があります。

作成アクションで、UI スレッドを呼び出して、UI スレッドで実際の作成を行います。

于 2013-01-05T12:59:14.800 に答える
0

VSデバッガーで一時停止した後、[デバッグ]/[Windows]メニューの[スレッド]ウィンドウを開きます。それらをすべて選択し、(コンテキストメニューから)フリーズします。次に、各スレッドをダブルクリックして、スタックしている場所を確認します。さらに、コールスタックを右クリックして、外部コードを表示します。

于 2013-01-03T03:38:24.643 に答える
0

そのような機会に私が使用するのが好きないくつかのトリックがあります:

この回答は既に.NET ランタイムで内部エラーをデバッグするにはどうすればよいですか? にあります。

しかし、これはあなたの問題をカバーするだけでなく、CLRが崩壊するまですべてのアクションを記録するはずです

IntelliTraceEvents And Call Information は、クラッシュが発生する前に何が起こったのかを正確に見つけるための驚くべきトリックです

ツール -> デバッグ -> 一般 -> .Net Framework デバッグを有効にする

+

ツール -> IntelliTace -> IntelliTraceEvents と呼び出し情報

+

[ツール] -> [IntelliTace] -> [このディレクトリに StorIntelliTace Recordings を設定]

ディレクトリを選択します

.netコードにステップインして、すべての関数呼び出しをトレースできるようにする必要があります。小さなサンプルプロジェクトで試してみましたが、うまくいきます

各デバッグ セッションの後、デバッグ セッションの記録を作成することを想定しています。間違っていなければCLRが死んでも設定ディレクトリ

これにより、CLR が崩壊する前に extact 呼び出しに到達できるはずです。

第二のトリック

本番環境で使用される可能性があるのは、次の素晴らしいフレームワークPostSharpです。

このチュートリアルに注意してください:

http://www.sharpcrafters.com/solutions/logging

説明どおりにポストシャープを使用した後。

システム内のすべての関数について、終了時に入力されたとき、および例外がスローされた場合はすべての変数をログに記録できます。

数十行のコードを使用してこれらすべてを実行します。

于 2013-01-10T12:17:55.020 に答える