I'm trying out Parallel.ForEachAsync and the compiler is kind enough to inform me that the body is a func that returns a ValueTask, not a Task.
Stopwatch sw = Stopwatch.StartNew();
var numbers = Enumerable.Range(start: 0, count: 10);
// Error: 'Task WorkAsync(int, CancellationToken)' has the wrong return type
await Parallel.ForEachAsync(
source: numbers,
parallelOptions: new ParallelOptions{ MaxDegreeOfParallelism = 2 },
body: WorkAsync);
async Task WorkAsync(int item, CancellationToken cancellationToken)
{
WriteLine($"Task {item} Start");
await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken).ConfigureAwait(false);
WriteLine($"Task {item} End");
}
void WriteLine(string s) => Console.WriteLine($"{sw.ElapsedMilliseconds, 3} Thread{Thread.CurrentThread.ManagedThreadId}: {s}");
A quick search yielded only ForEachAsync examples that use a lambda with multiple statements: async (x, ct) => { ...; await ...; }.
I feel that
body: async (item, cancellationToken) => await WorkAsync(item, cancellationToken).ConfigureAwait(false));
is significantly uglier than:
body: WorkAsync);
In the trivial example here I can obviously change the return type of the worker method, but it seems unwise to modify existing code to return ValueTasks.
Is there an obvious solution I have missed for creating beautiful code with Parallel.ForEachAsync?
I don't know if it qualifies as prettier, but you could consider doing this:
To be honest I think that the
Parallel.ForEachAsyncAPI would be better if it accepted aFunc<T, CancellationToken, Task>delegate as thebody, since the most common usage scenarios for this API are high latency I/O-bound operations over the network. For these scenarios, switching fromTasktoValueTaskmakes practically zero difference, in either performance or memory-efficiency. Reducing the general usability of the API in order to optimize some exotic scenarios withIValueTaskSource-backedbodydelegates, makes little sense to me. But this is what we have now, and it's certainly much prettier than what we had earlier, so I am not complaining too much.