4

数年前に実装された私のベース ViewModel は、UI の応答性を維持しながらタスクを実行するためのこの拡張メソッドを提供します*:

protected void Work(Action job)
{
    IsBusy = true;
    var stackTrace = new StackTrace();
    var task = Task.Factory.StartNew(job)
        .ContinueWith(failedTask => HandleException(failedTask, stackTrace), 
                      TaskContinuationOptions.OnlyOnFaulted)
        .ContinueWith(_ => { IsBusy = false; });
}

void HandleException(Task task, StackTrace stackTrace)
{
    Dispatcher.BeginInvoke(
        () => { throw new Exception(task.Exception.InnerException.ToString() + 
                                    stackTrace); });
}

IsBusy進行状況バーを表示するために UI から監視されるプロパティです。

背後にある考え方HandleExceptionsは、それらが監視されてから UI スレッドにスローされtry/catch、メソッド内のブロックによってキャッチされMain()、ユーザーにわかりやすいメッセージを表示してアプリを安全に閉じる前にログに記録されるというものです。ログに呼び出し元の情報が含まれるように、stackTrace が渡されます。

ただし、最近、次の Windows ダイアログで、ログもわかりやすいメッセージも表示されずにアプリケーションがクラッシュするというレポートを受け取り始めました。

クラッシュ

Windows イベント ログを見ると、次の EventData が得られました。

アプリケーション: xxxxApplication.Loader.exe

フレームワークのバージョン: v4.0.30319

説明: 未処理の例外が発生したため、プロセスが終了しました。

例外情報: System.AggregateException

スタック: System.Threading.Tasks.TaskExceptionHolder.Finalize() で

私は何か悪いことをしていContinueWith()ますか?

タスクの例外が何らかの形で監視されない可能性はありますか?


*: については知っていBackgroundWorkerます。これはおそらく当時はより良いアイデアのように見えたか、追加の利点がありました.

4

3 に答える 3

1

AppDomain.CurrentDomain.UnhandledExceptionを処理し て「わかりやすいメッセージ」を表示するか、(これが解決策でない場合) 少なくともこのイベント内のエラーをログに記録し、スタックトレースがどこにあるかを確認することをお勧めします。この「未処理」のタスク例外が発生します。

于 2012-10-27T10:04:37.017 に答える
0

よくわかりませんが、failedTask変数を介して元の例外を取得します。Task が失敗した場合は、null 以外を提供します。AggregateException

その Exception には、 AggregateException に含まれる各例外を処理し、例外が処理されたと見なすかどうかを指定できるデリゲートを提供できるHandle メソッドがあります。

つまり、Dispatcher スレッドで実際の例外を再スローする場合は、タスク チェーンを離れる前に、元の例外を処理済みとしてマークしたことを確認する必要があると思います。

于 2012-10-22T13:51:36.527 に答える