How can I await an array of tasks and stop waiting on first exception?

前端 未结 3 960
一向
一向 2020-12-03 21:49

I have an array of tasks and I am awaiting them with Task.WhenAll. My tasks are failing frequently, in which case I inform the user with a message box so that she can try ag

3条回答
  •  既然无缘
    2020-12-03 22:17

    I recently needed once again the WhenAllFailFast method, and I revised @ZaldronGG's excellent solution to make it a bit more performant (and more in line with Stephen Cleary's recommendations). The implementation below handles around 3,500,000 tasks per second in my PC.

    public static Task WhenAllFailFast(params Task[] tasks)
    {
        if (tasks is null) throw new ArgumentNullException(nameof(tasks));
        if (tasks.Length == 0) return Task.FromResult(new TResult[0]);
    
        var results = new TResult[tasks.Length];
        var remaining = tasks.Length;
        var tcs = new TaskCompletionSource(
            TaskCreationOptions.RunContinuationsAsynchronously);
    
        for (int i = 0; i < tasks.Length; i++)
        {
            var task = tasks[i];
            if (task == null) throw new ArgumentException(
                $"The {nameof(tasks)} argument included a null value.", nameof(tasks));
            HandleCompletion(task, i);
        }
        return tcs.Task;
    
        async void HandleCompletion(Task task, int index)
        {
            try
            {
                var result = await task.ConfigureAwait(false);
                results[index] = result;
                if (Interlocked.Decrement(ref remaining) == 0)
                {
                    tcs.TrySetResult(results);
                }
            }
            catch (OperationCanceledException)
            {
                tcs.TrySetCanceled();
            }
            catch (Exception ex)
            {
                tcs.TrySetException(ex);
            }
        }
    }
    

提交回复
热议问题