2017-12-29 32 views
1

スレッドNesting await in Parallel.ForEachには、複数の(MaxDegreeOfParallelism)非同期タスクを並列で実行するためにTask.WhenAllを使用するように提案された回答があり、前のタスクが完了するまで待機しません。タスクパラメータを含める方法タスクの配列例外処理で

public static Task ForEachAsync<T>(
     this IEnumerable<T> source, int dop, Func<T, Task> body) 
{ 
    return Task.WhenAll( 
     from partition in Partitioner.Create(source).GetPartitions(dop) 
     select Task.Run(async delegate { 
      using (partition) 
       while (partition.MoveNext()) 
        await body(partition.Current).ContinueWith(t => 
          { 
           //observe exceptions 
          }); 
})); 
} 

と体がパラメータを持っている場合、私はexceptions.e.gを処理するときに、パラメータ値を知りたい

ids.ForEachAsync(10, async id => 
{ 
    ICustomerRepo repo = new CustomerRepo(); 
    var cust = await repo.GetCustomer(id); 
    customers.Add(cust); 
}); 

のようにそれを呼び出します。 idのためにタスク本体が失敗した場合、特定のIDに対して起こったことを指定して、例外を記録する必要があります。

私は Accessing values in Task.ContinueWithを見ましたが、t.IsFaultedのときにパラメータにアクセスできませんでした。 (ブロックせず、すなわち非同期)

は最後に、私はラムダ本体の内側のtry/catchを追加したのだが、私はわからないが

ids.ForEachAsync(10, async id => 
{ 
    try 
    { 
     ICustomerRepo repo = new CustomerRepo(); 
     var cust = await repo.GetCustomer(id); 
     customers.Add(cust); 
    } 
    catch(Exception e) 
    { 
     _logger.LogError(e,” id=“+ id); 
    } 
}); 

は、それが正常に動作しない動作するようです。

体を待って、その後継続(ContinueWith(トン=> {...})内の電流を使用する前に、VAR電流= partition.Currentを使用するには、元の答えsuggestedの後半著者 - 。

ことができます誰も優れているアプローチ、確認の各アプローチのいずれも短所try/catchawaitラッピング

答えて

1

は結構です、見ていない:??Catch an exception thrown by an async method私の提案からは大きな差が(partition.Currentをキャプチャし、ContinueWith継続に注入する)、多分を除いて。キャプチャしていないのでもう少し効率的です関係している。また、それは少し読みやすく優雅だと私は思っています。ContinueWithは、 "古い"方法(事前async/await)のようなものです。

例では、例外処理の負担が呼び出し元(この場合は_logger.LogError)に渡されます。呼び出し元が例外を伝えるケースを処理するコード自体に埋め込まれたcatch-allとは対照的に、あなたが望むものであることを確認する必要があります。ForEachAsync次のようなもの:

while (partition.MoveNext()) 
{ 
    try 
    { 
     await body(partition.Current) 
    } 
    catch (Exception e) 
    { 
     // of course here you don't know the type of T (partition.Current) 
     // or anything else about the operation for that matter 
     LogError("error processing: " + partition.Current + ": " + e); 
    } 
} 
関連する問題