2

私はこのような実装をしています:

Task<IEnumerable<Item1>> GetItems1() 
{
    return RunRequest(async () => ParseItemsFromResponse(await(httpClient.Get(..))));
}

Task<IEnumerable<Item2>> GetItems2() 
{
    return RunRequest(async () => ParseItemsFromResponse(await httpClient.Get(..)));
}


TResult RunRequest<TResult>(Func<TResult> req)
{
    try
    {
        return req();
    }
    catch (Exception ex)
    {
        // Parse exception here and throw custom exceptions
    }
}

問題は無効な無名メソッドです。async () => ParseItemsFromResponse(..)

これはvoidを返し、aを返さないのでTask匿名メソッド内で例外がスローされても、実際にはそのメソッドによってキャッチされることはありません。tryそしてcatch以内RunRequest

これをリファクタリングする方法がありますか?


  • ただしないつかいますasync void。これらは、イベントハンドラ、またはaを受信または処理できない類似のメソッドを対象としています。Task結果。によってスローされた例外を防ぐことはできませんasync voidアプリケーションの未処理例外ハンドラを除く - Panagiotis Kanavos
  • 一般的にはアドバイスされる決して非同期関数でvoidを使用します。 - Bauss
  • 作るRunRequest取るTaskの代わりにFuncそして渡すhttpClient.Get()直接? - Mats391
  • コンパイラはそれを使用しませんRunRequestParseItemsFromResponseが何かを返さない限り、オーバーロードします。他にもありますかAction?このようにしないでください。var result=await httpClient.Get();ParseItems(result);きれいです - Panagiotis Kanavos
  • @ Mats391それは良い考えだ、なぜ私はそれについて考えなかったのか、ありがとう! - Don Box

1 답변


3

RunRequest取るべきFunc<Task<TResult>>、 など:

async Task<TResult> RunRequestAsync<TResult>(Func<Task<TResult>> req)
{
  try
  {
    return await req().ConfigureAwait(false);
  }
  catch (Exception ex)
  {
    // Parse exception here and throw custom exceptions
  }
}

それであなたのasyncラムダはに変換されますasync Task<T>の代わりにメソッドasync void

私はより多くの情報を持っています同期/非同期デリゲート私のブログに。


  • 電話する必要もありますかConfigureAwait(false)?それともコンテキストを元に戻さないことが最適化にすぎないのでしょうか。 - Don Box
  • @DonBox:これは単なる最適化です。 - Stephen Cleary

リンクされた質問


関連する質問

最近の質問