Die ganze Idee dahinter Parallel.ForEach()
ist, dass Sie eine Reihe von Threads haben und jeder Thread einen Teil der Sammlung verarbeitet. Wie Sie bemerkt haben, funktioniert dies nicht mit async
- await
, wo Sie den Thread für die Dauer des asynchronen Aufrufs freigeben möchten.
Sie könnten das "beheben", indem Sie die ForEach()
Threads blockieren , aber das macht den ganzen Punkt von async
- zunichte await
.
Sie können stattdessen TPL Dataflow verwenden Parallel.ForEach()
, das asynchrone Task
Daten gut unterstützt.
Insbesondere könnte Ihr Code mit einem geschrieben werden TransformBlock
, der jede ID Customer
mit dem async
Lambda in einen umwandelt . Dieser Block kann so konfiguriert werden, dass er parallel ausgeführt wird. Sie würden diesen Block mit einem verknüpfen, ActionBlock
der jeden Customer
in die Konsole schreibt . Nachdem Sie das Blocknetzwerk eingerichtet haben, können Sie Post()
jede ID dem TransformBlock
.
In Code:
var ids = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
var getCustomerBlock = new TransformBlock<string, Customer>(
async i =>
{
ICustomerRepo repo = new CustomerRepo();
return await repo.GetCustomer(i);
}, new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
});
var writeCustomerBlock = new ActionBlock<Customer>(c => Console.WriteLine(c.ID));
getCustomerBlock.LinkTo(
writeCustomerBlock, new DataflowLinkOptions
{
PropagateCompletion = true
});
foreach (var id in ids)
getCustomerBlock.Post(id);
getCustomerBlock.Complete();
writeCustomerBlock.Completion.Wait();
Obwohl Sie wahrscheinlich die Parallelität der TransformBlock
auf eine kleine Konstante beschränken möchten . Sie können auch die Kapazität von einschränken TransformBlock
und die Elemente asynchron hinzufügen SendAsync()
, z. B. wenn die Sammlung zu groß ist.
Ein zusätzlicher Vorteil im Vergleich zu Ihrem Code (falls er funktioniert hat) ist, dass das Schreiben beginnt, sobald ein einzelnes Element fertig ist, und nicht wartet, bis die gesamte Verarbeitung abgeschlossen ist.