Task.WhenAll 方法

定义

创建一个任务,该任务将在所有提供的任务完成时完成。

重载

WhenAll(IEnumerable<Task>)

创建一个任务,该任务将在可枚举集合中的所有 Task 对象完成时完成。

WhenAll(ReadOnlySpan<Task>)

创建一个任务,该任务将在所有提供的任务完成时完成。

WhenAll(Task[])

创建一个任务,该任务将在数组中的所有 Task 对象完成时完成。

WhenAll<TResult>(ReadOnlySpan<Task<TResult>>)

创建一个任务,该任务将在所有提供的任务完成时完成。

WhenAll<TResult>(IEnumerable<Task<TResult>>)

创建一个任务,该任务将在可枚举集合中的所有 Task<TResult> 对象完成时完成。

WhenAll<TResult>(Task<TResult>[])

创建一个任务,该任务将在数组中的所有 Task<TResult> 对象完成时完成。

WhenAll(IEnumerable<Task>)

Source:
Task.cs
Source:
Task.cs
Source:
Task.cs

创建一个任务,该任务将在可枚举集合中的所有 Task 对象完成时完成。

C#
public static System.Threading.Tasks.Task WhenAll (System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task> tasks);

参数

tasks
IEnumerable<Task>

要等待完成的任务。

返回

表示所有提供任务的完成的任务。

例外

tasks 参数 null

tasks 集合包含 null 任务。

示例

以下示例创建一组任务,用于对数组中的 URL 执行 ping 操作。 任务存储在传递给 WhenAll(IEnumerable<Task>) 方法的 List<Task> 集合中。 调用 Wait 方法可确保所有线程都已完成之后,该示例将检查 Task.Status 属性以确定是否有任何任务出错。

C#
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      int failed = 0;
      var tasks = new List<Task>();
      String[] urls = { "www.adatum.com", "www.cohovineyard.com",
                        "www.cohowinery.com", "www.northwindtraders.com",
                        "www.contoso.com" };
      
      foreach (var value in urls) {
         var url = value;
         tasks.Add(Task.Run( () => { var png = new Ping();
                                     try {
                                        var reply = png.Send(url);
                                        if (! (reply.Status == IPStatus.Success)) {
                                           Interlocked.Increment(ref failed);
                                           throw new TimeoutException("Unable to reach " + url + ".");
                                        }
                                     }
                                     catch (PingException) {
                                        Interlocked.Increment(ref failed);
                                        throw;
                                     }
                                   }));
      }
      Task t = Task.WhenAll(tasks);
      try {
         t.Wait();
      }
      catch {}   

      if (t.Status == TaskStatus.RanToCompletion)
         Console.WriteLine("All ping attempts succeeded.");
      else if (t.Status == TaskStatus.Faulted)
         Console.WriteLine("{0} ping attempts failed", failed);      
   }
}
// The example displays output like the following:
//       5 ping attempts failed

注解

当对一组任务的状态或一组任务引发的异常感兴趣时,通常会调用返回 Task 对象的 WhenAll 方法的重载。

备注

WhenAll(IEnumerable<Task>) 方法的调用不会阻止调用线程。

如果提供的任何任务都以错误状态完成,则返回的任务也将处于 Faulted 状态,其中其异常将包含每个提供的任务的未包装异常集的聚合。

如果提供的任务均未出错,但其中至少一个任务已取消,则返回的任务将以 Canceled 状态结束。

如果没有任何任务出错且未取消任何任务,则生成的任务将以 RanToCompletion 状态结束。

如果提供的数组/可枚举不包含任何任务,则返回的任务将在返回给调用方之前立即转换为 RanToCompletion 状态。

适用于

.NET 9 和其他版本
产品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1
UWP 10.0

WhenAll(ReadOnlySpan<Task>)

创建一个任务,该任务将在所有提供的任务完成时完成。

C#
public static System.Threading.Tasks.Task WhenAll (scoped ReadOnlySpan<System.Threading.Tasks.Task> tasks);

参数

tasks
ReadOnlySpan<Task>

要等待完成的任务。

返回

表示所有提供任务的完成的任务。

例外

tasks 数组包含 null 任务。

注解

如果提供的任何任务都以错误状态完成,则返回的任务也将处于“出错”状态,其中异常将包含每个提供任务中未包装的异常集的聚合。

如果提供的任务均未出错,但至少其中一个任务已取消,则返回的任务将以“已取消”状态结束。

如果没有任何任务出错且未取消任何任务,则生成的任务将以 RanToCompletion 状态结束。

如果提供的跨度不包含任何任务,则返回的任务将在返回给调用方之前立即转换为 RanToCompletion 状态。

适用于

.NET 9
产品 版本
.NET 9

WhenAll(Task[])

Source:
Task.cs
Source:
Task.cs
Source:
Task.cs

创建一个任务,该任务将在数组中的所有 Task 对象完成时完成。

C#
public static System.Threading.Tasks.Task WhenAll (params System.Threading.Tasks.Task[] tasks);

参数

tasks
Task[]

要等待完成的任务。

返回

表示所有提供任务的完成的任务。

例外

tasks 参数 null

tasks 数组包含 null 任务。

示例

以下示例创建一组任务,用于对数组中的 URL 执行 ping 操作。 任务存储在 List<Task> 集合中,该集合转换为数组并传递给 WhenAll(IEnumerable<Task>) 方法。 调用 Wait 方法可确保所有线程都已完成之后,该示例将检查 Task.Status 属性以确定是否有任何任务出错。

C#
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static async Task Main()
   {
      int failed = 0;
      var tasks = new List<Task>();
      String[] urls = { "www.adatum.com", "www.cohovineyard.com",
                        "www.cohowinery.com", "www.northwindtraders.com",
                        "www.contoso.com" };
      
      foreach (var value in urls) {
         var url = value;
         tasks.Add(Task.Run( () => { var png = new Ping();
                                     try {
                                        var reply = png.Send(url);
                                        if (! (reply.Status == IPStatus.Success)) {
                                           Interlocked.Increment(ref failed);
                                           throw new TimeoutException("Unable to reach " + url + ".");
                                        }
                                     }
                                     catch (PingException) {
                                        Interlocked.Increment(ref failed);
                                        throw;
                                     }
                                   }));
      }
      Task t = Task.WhenAll(tasks.ToArray());
      try {
         await t;
      }
      catch {}   

      if (t.Status == TaskStatus.RanToCompletion)
         Console.WriteLine("All ping attempts succeeded.");
      else if (t.Status == TaskStatus.Faulted)
         Console.WriteLine("{0} ping attempts failed", failed);      
   }
}
// The example displays output like the following:
//       5 ping attempts failed

注解

当对一组任务的状态或一组任务引发的异常感兴趣时,通常会调用返回 Task 对象的 WhenAll 方法的重载。

备注

WhenAll(Task[]) 方法的调用不会阻止调用线程。

如果提供的任何任务都以错误状态完成,则返回的任务也将处于 Faulted 状态,其中其异常将包含每个提供的任务的未包装异常集的聚合。

如果提供的任务均未出错,但其中至少一个任务已取消,则返回的任务将以 Canceled 状态结束。

如果没有任何任务出错且未取消任何任务,则生成的任务将以 RanToCompletion 状态结束。

如果提供的数组/可枚举不包含任何任务,则返回的任务将在返回给调用方之前立即转换为 RanToCompletion 状态。

适用于

.NET 9 和其他版本
产品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1
UWP 10.0

WhenAll<TResult>(ReadOnlySpan<Task<TResult>>)

创建一个任务,该任务将在所有提供的任务完成时完成。

C#
public static System.Threading.Tasks.Task<TResult[]> WhenAll<TResult> (scoped ReadOnlySpan<System.Threading.Tasks.Task<TResult>> tasks);

类型参数

TResult

参数

tasks
ReadOnlySpan<Task<TResult>>

要等待完成的任务。

返回

Task<TResult[]>

表示所有提供任务的完成的任务。

例外

tasks 数组包含 null 任务。

注解

如果提供的任何任务都以错误状态完成,则返回的任务也将处于“出错”状态,其中异常将包含每个提供任务中未包装的异常集的聚合。

如果提供的任务均未出错,但至少其中一个任务已取消,则返回的任务将以“已取消”状态结束。

如果没有任何任务出错且未取消任何任务,则生成的任务将以 RanToCompletion 状态结束。 返回的任务的结果将设置为一个数组,该数组包含所提供的任务的所有结果,其顺序与提供的顺序相同(例如,如果输入任务数组包含 t1、t2、t3,则输出任务的结果将返回一个 TResult[],其中 arr[0] == t1)。Result, arr[1] == t2。结果和 arr[2] == t3。结果)。

如果提供的数组/可枚举不包含任何任务,则返回的任务将在返回给调用方之前立即转换为 RanToCompletion 状态。 返回的 TResult[] 将是 0 个元素的数组。

适用于

.NET 9
产品 版本
.NET 9

WhenAll<TResult>(IEnumerable<Task<TResult>>)

Source:
Task.cs
Source:
Task.cs
Source:
Task.cs

创建一个任务,该任务将在可枚举集合中的所有 Task<TResult> 对象完成时完成。

C#
public static System.Threading.Tasks.Task<TResult[]> WhenAll<TResult> (System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<TResult>> tasks);

类型参数

TResult

已完成任务的类型。

参数

tasks
IEnumerable<Task<TResult>>

要等待完成的任务。

返回

Task<TResult[]>

表示所有提供任务的完成的任务。

例外

tasks 参数 null

tasks 集合包含 null 任务。

示例

以下示例创建 10 个任务,每个任务实例化一个随机数生成器,该生成器在 1 到 1,000 之间创建 1,000 个随机数并计算其平均值。 Delay(Int32) 方法用于延迟随机数生成器的实例化,以便不会使用相同的种子值创建它们。 然后,对 WhenAll 方法的调用返回一个 Int64 数组,其中包含每个任务计算的平均值。 然后,这些值用于计算总体平均值。

C#
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var tasks = new List<Task<long>>();
      for (int ctr = 1; ctr <= 10; ctr++) {
         int delayInterval = 18 * ctr;
         tasks.Add(Task.Run(async () => { long total = 0;
                                          await Task.Delay(delayInterval);
                                          var rnd = new Random();
                                          // Generate 1,000 random numbers.
                                          for (int n = 1; n <= 1000; n++)
                                             total += rnd.Next(0, 1000);
                                          return total; } ));
      }
      var continuation = Task.WhenAll(tasks);
      try {
         continuation.Wait();
      }
      catch (AggregateException)
      { }
   
      if (continuation.Status == TaskStatus.RanToCompletion) {
         long grandTotal = 0;
         foreach (var result in continuation.Result) {
            grandTotal += result;
            Console.WriteLine("Mean: {0:N2}, n = 1,000", result/1000.0);
         }
   
         Console.WriteLine("\nMean of Means: {0:N2}, n = 10,000",
                           grandTotal/10000);
      }
      // Display information on faulted tasks.
      else {
         foreach (var t in tasks) {
            Console.WriteLine("Task {0}: {1}", t.Id, t.Status);
         }
      }
   }
}
// The example displays output like the following:
//       Mean: 506.34, n = 1,000
//       Mean: 504.69, n = 1,000
//       Mean: 489.32, n = 1,000
//       Mean: 505.96, n = 1,000
//       Mean: 515.31, n = 1,000
//       Mean: 499.94, n = 1,000
//       Mean: 496.92, n = 1,000
//       Mean: 508.58, n = 1,000
//       Mean: 494.88, n = 1,000
//       Mean: 493.53, n = 1,000
//
//       Mean of Means: 501.55, n = 10,000

在这种情况下,十个单个任务存储在 List<T> 对象中。 List<T> 实现 IEnumerable<T> 接口。

注解

WhenAll<TResult>(IEnumerable<Task<TResult>>) 方法的调用不会阻止调用线程。 但是,对返回 Result 属性的调用确实会阻止调用线程。

如果提供的任何任务都以错误状态完成,则返回的任务也将处于 Faulted 状态,其中其异常将包含每个提供的任务的未包装异常集的聚合。

如果提供的任务均未出错,但其中至少一个任务已取消,则返回的任务将以 Canceled 状态结束。

如果没有任何任务出错且未取消任何任务,则生成的任务将以 RanToCompletion 状态结束。 返回任务的 Task<TResult>.Result 属性将设置为一个数组,该数组包含所提供的任务的所有结果,其顺序与提供的顺序相同(例如,如果输入任务数组包含 t1、t2、t3,则输出任务的 Task<TResult>.Result 属性将返回一个 TResult[],其中 arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result)

如果 tasks 参数不包含任何任务,则返回的任务将在返回给调用方之前立即转换为 RanToCompletion 状态。 返回的 TResult[] 将是 0 个元素的数组。

适用于

.NET 9 和其他版本
产品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1
UWP 10.0

WhenAll<TResult>(Task<TResult>[])

Source:
Task.cs
Source:
Task.cs
Source:
Task.cs

创建一个任务,该任务将在数组中的所有 Task<TResult> 对象完成时完成。

C#
public static System.Threading.Tasks.Task<TResult[]> WhenAll<TResult> (params System.Threading.Tasks.Task<TResult>[] tasks);

类型参数

TResult

已完成任务的类型。

参数

tasks
Task<TResult>[]

要等待完成的任务。

返回

Task<TResult[]>

表示所有提供任务的完成的任务。

例外

tasks 参数 null

tasks 数组包含 null 任务。

示例

以下示例创建 10 个任务,每个任务实例化一个随机数生成器,该生成器在 1 到 1,000 之间创建 1,000 个随机数并计算其平均值。 在这种情况下,十个单个任务存储在 Task<Int64> 数组中。 Delay(Int32) 方法用于延迟随机数生成器的实例化,以便不会使用相同的种子值创建它们。 然后,对 WhenAll 方法的调用返回一个 Int64 数组,其中包含每个任务计算的平均值。 然后,这些值用于计算总体平均值。

C#
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      var tasks = new Task<long>[10];
      for (int ctr = 1; ctr <= 10; ctr++) {
         int delayInterval = 18 * ctr;
         tasks[ctr - 1] = Task.Run(async () => { long total = 0;
                                                 await Task.Delay(delayInterval);
                                                 var rnd = new Random();
                                                 // Generate 1,000 random numbers.
                                                 for (int n = 1; n <= 1000; n++)
                                                    total += rnd.Next(0, 1000);

                                                 return total; } );
      }
      var continuation = Task.WhenAll(tasks);
      try {
         continuation.Wait();
      }
      catch (AggregateException)
      {}
   
      if (continuation.Status == TaskStatus.RanToCompletion) {
         long grandTotal = 0;
         foreach (var result in continuation.Result) {
            grandTotal += result;
            Console.WriteLine("Mean: {0:N2}, n = 1,000", result/1000.0);
         }
   
         Console.WriteLine("\nMean of Means: {0:N2}, n = 10,000",
                           grandTotal/10000);
      }
      // Display information on faulted tasks.
      else { 
         foreach (var t in tasks)
            Console.WriteLine("Task {0}: {1}", t.Id, t.Status);
      }
   }
}
// The example displays output like the following:
//       Mean: 506.38, n = 1,000
//       Mean: 501.01, n = 1,000
//       Mean: 505.36, n = 1,000
//       Mean: 492.00, n = 1,000
//       Mean: 508.36, n = 1,000
//       Mean: 503.99, n = 1,000
//       Mean: 504.95, n = 1,000
//       Mean: 508.58, n = 1,000
//       Mean: 490.23, n = 1,000
//       Mean: 501.59, n = 1,000
//
//       Mean of Means: 502.00, n = 10,000

注解

WhenAll<TResult>(Task<TResult>[]) 方法的调用不会阻止调用线程。 但是,对返回 Result 属性的调用确实会阻止调用线程。

如果提供的任何任务都以错误状态完成,则返回的任务也将处于 Faulted 状态,其中其异常将包含每个提供的任务的未包装异常集的聚合。

如果提供的任务均未出错,但其中至少一个任务已取消,则返回的任务将以 Canceled 状态结束。

如果没有任何任务出错且未取消任何任务,则生成的任务将以 RanToCompletion 状态结束。 返回任务的 Result 将设置为一个数组,该数组包含所提供的任务的所有结果,其顺序与提供的顺序相同(例如,如果输入任务数组包含 t1、t2、t3,则输出任务的 Result 将返回 TResult[],其中 arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result)

如果提供的数组/可枚举不包含任何任务,则返回的任务将在返回给调用方之前立即转换为 RanToCompletion 状态。 返回的 TResult[] 将是 0 个元素的数组。

适用于

.NET 9 和其他版本
产品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1
UWP 10.0