5

のために忘れては、以下の「ファイア・アンド・フォーゲット」ユースケースを考えてみましょう:例外火の取り扱いと(.NET 4.5で)C#5

呼び出し側が私の方法からいくつかのデータを要求します。私のメソッドは、キャッシュがデータがすでに存在するかどうかをチェックします。そうでなければ、ソースから取り出してキャッシュします。呼び出し元は、結果を取得する前にキャッシングが発生するのを待つ必要はなく、キャッシングが失敗した場合に呼び出し元が結果を取得しないようにしてはいけません。私が今日持っているもの、次のようになります。

public Foo GetFoo(string fooKey) 
{ 
    // look for Foo with fooKey in cache 
    // if Foo is not found, get Foo with fooKey from source 
    // and assign it to local variable myFoo 
    Task cacheTask 
      = Task.Run 
       (
        () => CacheFoo(myFoo)// fire-and-forget the caching of myFoo 
       ); 
    return myFoo; 
} 

CacheFooが例外をスローした場合、それは未観測行き、最終的には(.NET 4.5で)それはフレームワークによって飲み込まます。私はむしろ例外を自分自身で掃除する最後のショットを持っているだろうが、私は現在のスレッドをブロックしたくない。それを行う最善の方法は何ですか?ここで

は私が

try 
{ 
    ... 
    cacheTask.ContinueWith 
      (
       (e) => { 
         if (cacheTask.IsFaulted) 
          { 
          /* log cacheTask.Exception */; 
          } 
         } 
       , TaskContinuationOptions.OnlyOnFaulted 
      ); 
} 

を試してみた何より良い方法はありますか? IsFaultedでif文が必要か、それとも "OnlyOnFaulted"を指定しているので冗長であるのですか?

ご意見・ご提案は大変ありがとうございます。

+0

タスクをfire-and-forget ...soとしてマークすることができればいいですか?Wait/ContinueWithが可能です。そして、このケースでは誰も例外を処理するためにアプリケーションをクラッシュさせるので、例外がスローされた時点のローカル変数とヒープを見ることができる素敵なダンプファイルがあります。 – mmmmmmmm

答えて

7

つの事:

  • いいえ、あなたはTask.IsFaulted propertyを必要としません。コールバックは、障害が発生した場合にのみ起動します
  • cacheTaskをキャプチャする必要はありません。あなたのコールバックのeは同じタスクなので、代わりにそれを使うこともできます。 (そして、同じデリゲートがすべてタスクに使用することができます。)
  • あなたはいつも同じ方法でログインしている場合、あなたはそれが簡単にこの
  • Asを行うために作成するタスクの拡張メソッドを記述することもできますハンドラーを追加する代わりに、TaskScheduler.UnobservedTaskExceptionを購読し、そこにログを記録することを検討することができます。
+0

ワオ。それは速かった。ありがとうジョン! –

+0

私は把握できませんでした。これは.NET 4.0と4.5の間に違いがありますか?で、それ何? –

+2

@ГеннадийВанинНовосибирск:はい、違いはありますが、ここではそれが適切かどうかはわかりません。 .NET 4.0では、タスクが監視されていない方法でフォルトが発生した場合、プロセス全体が終了します。 .NET 4.5ではありません。 –

関連する問題