I have an async Func<> where I "await" for a async method. I want to make a lot of parallel calls to that Func<> using TaskFactory.StartNew, like the below code, but I get the followin error:
error converting
'System.Threading.Tasks.Task<System.Threading.Tasks.Task<Result>>'
to'System.Threading.Tasks.Task<Result>'
How can I have a parallel calls for a async method?
Func<object, Task<Result>> action = async (object m) =>
{
try
{
return await Send<Message, Result>(m as Message);
}
catch (Exception exc)
{
Result result = new Result();
(result as ResponseBaseDto).Success = false;
(result as ResponseBaseDto).ErrorList = new List<Entities.Common.ErrorDto>()
{
new Entities.Common.ErrorDto{ Code = 9999, Message = exc.Message }
};
return result;
}
};
// Error on request.ForEach
request.ForEach(r => sending.Add(taskFactory.StartNew<Task<Result>>(action, r)));
var tareas = sending.ToArray();
await Task.WhenAll(tareas);
return tareas.Select(s => s.Result).ToList();
Assuming you are using a taskFactory.StartNew(
instead of Task.Run(
because you have a special configured TaskFactory
you need to unwrap the result of the StartNew, which will be a Task<Task<Result>>
. The easiest solution is use the .Unwrap()
extension method to unwrap the nested task.
You also should replace the .ForEach(r=> sending.Add(
with a .Select(r =>
statement to reduce the number of times the list is iterated over. If you are returning a IEnumerable<Result>
instead of a List<Result>
you can remove your final .ToList()
too.
var tareas = request.Select(r => taskFactory.StartNew<Task<Result>>(action, r).Unwrap());
var results = await Task.WhenAll(tareas); //results is a `Result[]`
return results.ToList(); // you may not need this .ToList().
If you are not using a special task factory your code can be simplified to
var tareas = request.Select(r => Task.Run(() => action(r)));
var results = await Task.WhenAll(tareas); //results is a `Result[]`
return results.ToList(); // you may not need this .ToList().