I'm trying to change Stephen Toub's ForEachAsync<T>
extension method into an extension which returns a result...
Stephen's extension:
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);
}));
}
My approach (not working; tasks get executed but result is wrong)
public static Task<TResult[]> ForEachAsync<T, TResult>(this IList<T> source,
int degreeOfParallelism, Func<T, Task<TResult>> body)
{
return Task.WhenAll<TResult>(
from partition in Partitioner.Create(source).GetPartitions(degreeOfParallelism)
select Task.Run<TResult>(async () =
{
using (partition)
while (partition.MoveNext())
await body(partition.Current); // When I "return await",
// I get good results but only one per partition
return default(TResult);
}));
}
I know I somehow have to return (WhenAll
?) the results from the last part but I didn't yet figure out how to do it...
Update: The result I get is just degreeOfParallelism
times null (I guess because of default(TResult)
) even though all the tasks get executed. I also tried to return await body(...)
and then the result was fine, but only degreeOfParallelism
number of tasks got executed.
default(TResult)
doesn't seem like a good start. It would help if you'd provide a short but complete program demonstrating the problem, including sample input, expected output and actual output. (I strongly suspect you wantSelectMany
instead ofSelect
here, basically...) – AreopagusFunc<T>
with no name. Again, if you'd posted a short but complete example to start with, you could be confident that it would be compile because it would be your exact code. – AreopagusSemaphoreSlim
. I just tend to avoid parallel code unless there's a need for it (i.e., CPU-heavy code, which is not the case here). – Sena