• 若需要执行若干个任务,只需要对其中任意一个的完成进行响应。如:对一个操作进行多种独立的尝试,只要一个尝试完成,任务就算完成。

    • 可以使用Task.WhenAny方法,该方法的参数是一批任务,当其中任意一个任务完成时就会返回。作为返回结果的 Task 对象,就是那个完成的任务,即表示提供的任务之一已完成的任务。

    • public static Task<Task> WhenAny(params Task[] tasks);
    • 下示简单例子:
    1. // 返回第一个响应的 URL 的数据长度。
    2. private static async Task<int> FirstRespondingUrlAsync(string urlA, string urlB)
    3. {
    4. var httpClient = new HttpClient();
    5. // 并发地开始两个下载任务。
    6. Task<byte[]> downloadTaskA = httpClient.GetByteArrayAsync(urlA);
    7. Task<byte[]> downloadTaskB = httpClient.GetByteArrayAsync(urlB);
    8. // 等待任意一个任务完成。
    9. Task<byte[]> completedTask =
    10. await Task.WhenAny(downloadTaskA, downloadTaskB);
    11. // 返回从 URL 得到的数据的长度。
    12. byte[] data = await completedTask;
    13. return data.Length;
    14. }

    注意,返回的任务将在提供的任何任务完成时完成。

    返回的任务将始终以 RanToCompletion 状态结束,其 Result 设置为完成的第一个任务。 即使第一个完成的任务以或Faulted状态结束Canceled,也是如此。

    如果这个任务完成时有异常,这个异常也不会传递给Task.WhenAny 返回的 Task 对象。因此,通常需要在 Task 对象完成后继续使用 await。

    注意,第一个任务完成后,考虑是否要取消剩下的任务。如果其他任务没有被取消,也没有被继续 await,那它们就处于被遗弃的状态。

    被遗弃的任务会继续运行直到完成,它们的结果会被忽略,抛出的任何异常也会被忽略。