2017-03-06 10 views
1

私は自分自身を仕事で混乱させてしまいました。そして、私はそれを抜け出す良い方法がないとは思っていません。「観察されないタスク」の例外を回避するにはどうすればよいですか?

私はデータを持っています私は2つの異なるAPIから非同期にフェッチするつもりです。接続は疑わしいです、私はどれくらい待つことができるか厳しい時間制約があります。望ましい動作は、「2秒間が経過しても2つのデータセットを取得するまでに2秒間待つ必要があります。何も完了していなくても完了します。」

私はこのようなjankyセットアップの一種でこれを引っ張っ:(それはすでにワーカースレッド上で動作するので、同期待ちが問題ではありません。)

Task<IData> firstTask = _firstDataSource.GetDataAsync() 
Task<IData> secondTask = _secondDataSource.GetDataAsync() 

var whenBothTasksFinish = Task.WhenAll(firstTask, secondTask); 

var timeoutTask = Task.Delay(TimeSpan.FromSeconds(2)); 

Task.WhenAny(whenBothTasksFinish, timeoutTask).Wait() 

bool timedOut = timeoutTask.IsCompleted 

if (timedOut) { 
    return newIData[0]; 
} 

var sources = new List<IData>(); 
if (firstTask.IsCompleted && !firstTask.IsFaulted) { 
    sources.Add(firstTask.Result); 
} else if (firstTask.IsFaulted) { 
    LogException(firstTask.Exception); 
} 

// Same block as above for secondTask 

をそれは厄介だが、私がいました私がそれを書いた時は窮屈だった。多分、それについてもっと良い方法があります、それは今夜私の心にあるでしょう。今、私はこの問題を解決する方法について混乱しています。

問題はです。ネットワーク接続がオフになっていると、両方のIDataタスクが失敗します。私は例外をログするので、UnobservedTaskExceptionにつながる条件を満たします。しかし、その例外もTask.WhenAll()とおそらくTask.WhenAny()にバブルします。それは最終的にファイナライズされ、私のアプリはUnobservedTaskExceptionをスローします。奇妙なことに、それは一貫してアプリをクラッシュさせるようには見えないが、それは時々なので、私は心配している。

私は周りを見回していると私はこれに対処できた一つの方法は、かなり単純な継続であるようにそう:

whenBothTasksFinish.ContinueWith(t => LogException(t.Exception), TaskContinuationOptions.OnlyOnFaulted); 

私はどのように現在の構造好きな私はちょうどそれをやっていないよ唯一の理由がありますより個別化されたログメッセージを提供できます。例外を投げたタスクが気になります。私は厄介なAggregateExceptionをログに記録したくありませんが、それを解明するにはあまり見ていない。

これは遅れており、私はこのアルゴリズムを再考するのに多くの時間を費やしていません。タスクの例外を認識していることを確認する方法か、これを再構成して、多くの可動部品を必要とせずに望む結果を得る方法がありますか?

答えて

0

私は別の多くのことを試みたが、このソリューションに到着しました:通常の状況で

whenBothTasksFinish.ContinueWith((parent) => { 
    var flattened = parent.Exception.Flatten(); 
    flattened.Handle((ex) => true); 
    }, TaskContinuationOptions.OnlyOnFaulted); 

、これは悪い考えです。これは空のtry/catchと同じです。しかし私のシナリオでは、後で別々に各例外を処理します。これにより、フレームワークは私がWhenAll(からの例外を処理していないと不平を言って終了します。

奇妙なこと:Xamarin Studioでデバッグするときに、ブレークポイントを長すぎると、継続が実行される前にWhenAll()タスクが収集されることがあります。私はおそらくGC.KeepAlive()しかしそれを介して対処することができます。

関連する問題