Possilbe issues when using CombineAsyncLeft if the IEnumerable<Task<Result> must be iterated in order
Opened this issue · 3 comments
This mean that a code like:
ids.Select(async () => Result.Try(await dbContext.DataSet.FirstOrDefault(e => e.Id = id))
.Combine()
May result with an error:
second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
I think we should have an option:
public enum AsyncExecutionOrder { Unordered = 0 , InOrder }
public static async Task<Result<IEnumerable<T>>> Combine<T>(this IEnumerable<Task<Result<T>>> tasks, string errorMessageSeparator = null, AsyncExecutionOrder order= TaskCombineOrder.Unordered)
{
Result<T>[] results = (order == AsyncExecutionOrder .Unordered)
? await Task.WhenAll(tasks).DefaultAwait();
: await tasks.ExecuteInOrder()
return results.Combine(errorMessageSeparator);
}
public static async Task<Result<IEnumerable<T>>> ExecuteInOrder<T>(this IEnumerable<Task<Result<T>>> tasks)
{
List<Result<T>> results = new List<Result<T>>();
foreach (var task in tasks)
{
results.Add(await task);
}
return results;
}
I tested it on my case with:
public static async Task<Result<IEnumerable<T>>> CombineInOrder<T>(this IEnumerable<Task<Result<T>>> tasks, string? errorMessageSeparator = null)
{
List<Result<T>> results = new List<Result<T>>();
foreach (var task in tasks)
{
results.Add(await task);
}
return results.Combine(errorMessageSeparator);
}
and it fix the async issue of the DbContext.
I can implement it if this suggestion will be approved.
We can add the second method (CombineInOrder
), but I don't think the AsyncExecutionOrder
enum and the additional argument in Combine
are needed.
@vkhorikov I have a branch I want to push for a PR but I get 403. Can you please add me as a contributer?
@YudApps You need to create a fork first, commit/push your changes and open a PR then. Here are the guidelines: https://github.com/MarcDiethelm/contributing/blob/master/README.md