Task.WhenAll 和 Task.WhenAny
知识点
Task.WhenAll 基础
- 并行等待:等待所有任务完成,所有任务并行执行
- 结果收集:自动收集所有任务的返回值到数组中
- 异常聚合:收集所有任务的异常,第一个异常会被抛出
- 性能优势:比逐个等待任务更高效
Task.WhenAny 基础
- 竞争执行:等待任意一个任务完成即返回
- 快速响应:获取最快完成的任务结果
- 超时实现:常用于实现超时机制
- 冗余处理:多个数据源中选择最快的响应
使用场景对比
- WhenAll:需要所有结果才能继续的场景(如数据聚合)
- WhenAny:任意一个结果就足够的场景(如多服务器请求)
- 组合使用:复杂场景中两者可以组合使用
- 错误处理:两者在异常处理上有不同的行为
代码样例
Task.WhenAll 基本使用
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
public class WhenAllBasicDemo
{
public static void DemonstrateWhenAllBasic()
{
Console.WriteLine("=== Task.WhenAll 基本使用演示 ===");
// 1. 无返回值任务的 WhenAll
Console.WriteLine("1. 无返回值任务的 WhenAll:");
DemonstrateWhenAllVoidTasks();
// 2. 有返回值任务的 WhenAll
Console.WriteLine("\n2. 有返回值任务的 WhenAll:");
DemonstrateWhenAllWithResults();
// 3. 混合类型任务的处理
Console.WriteLine("\n3. 混合类型任务的处理:");
DemonstrateMixedTaskTypes();
Console.WriteLine("Task.WhenAll 基本使用演示完成\n");
}
private static void DemonstrateWhenAllVoidTasks()
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// 创建多个无返回值任务
Task[] tasks = new Task[]
{
Task.Run(() =>
{
Console.WriteLine(" 任务A开始");
Thread.Sleep(1000);
Console.WriteLine(" 任务A完成");
}),
Task.Run(() =>
{
Console.WriteLine(" 任务B开始");
Thread.Sleep(1500);
Console.WriteLine(" 任务B完成");
}),
Task.Run(() =>
{
Console.WriteLine(" 任务C开始");
Thread.Sleep(800);
Console.WriteLine(" 任务C完成");
})
};
// 等待所有任务完成
Task.WhenAll(tasks).Wait();
stopwatch.Stop();
Console.WriteLine($" 所有任务完成,总耗时: {stopwatch.ElapsedMilliseconds}ms");
}
private static void DemonstrateWhenAllWithResults()
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// 创建多个有返回值的任务
Task<int>[] calculationTasks = new Task<int>[]
{
Task.Run(() =>
{
Console.WriteLine(" 计算任务1: 求和 1-100");
Thread.Sleep(500);
return Enumerable.Range(1, 100).Sum();
}),
Task.Run(() =>
{
Console.WriteLine(" 计算任务2: 求积 1-10");
Thread.Sleep(800);
return Enumerable.Range(1, 10).Aggregate(1, (acc, x) => acc * x);
}),
Task.Run(() =>
{
Console.WriteLine(" 计算任务3: 求平方和 1-20");
Thread.Sleep(600);
return Enumerable.Range(1, 20).Select(x => x * x).Sum();
})
};
// 等待所有任务并获取结果
int[] results = Task.WhenAll(calculationTasks).Result;
stopwatch.Stop();
Console.WriteLine(" 所有计算完成:");
for (int i = 0; i < results.Length; i++)
{
Console.WriteLine($" 计算任务{i + 1}结果: {results[i]}");
}
Console.WriteLine($" 总耗时: {stopwatch.ElapsedMilliseconds}ms");
}
private static void DemonstrateMixedTaskTypes()
{
// 字符串任务
Task<string>[] stringTasks = new Task<string>[]
{
Task.Run(() =>
{
Thread.Sleep(400);
return "Hello";
}),
Task.Run(() =>
{
Thread.Sleep(600);
return "World";
}),
Task.Run(() =>
{
Thread.Sleep(300);
return "!";
})
};
// 数字任务
Task<int>[] numberTasks = new Task<int>[]
{
Task.Run(() =>
{
Thread.Sleep(500);
return 42;
}),
Task.Run(() =>
{
Thread.Sleep(700);
return 100;
})
};
// 分别等待不同类型的任务
Task<string[]> stringResults = Task.WhenAll(stringTasks);
Task<int[]> numberResults = Task.WhenAll(numberTasks);
// 等待所有分组完成
Task.WhenAll(stringResults, numberResults).Wait();
Console.WriteLine(" 字符串结果: " + string.Join(" ", stringResults.Result));
Console.WriteLine(" 数字结果: " + string.Join(", ", numberResults.Result));
}
}
Task.WhenAny 基本使用
public class WhenAnyBasicDemo
{
public static void DemonstrateWhenAnyBasic()
{
Console.WriteLine("=== Task.WhenAny 基本使用演示 ===");
// 1. 基本的 WhenAny
Console.WriteLine("1. 基本的 WhenAny:");
DemonstrateBasicWhenAny();
// 2. 获取最快的结果
Console.WriteLine("\n2. 获取最快的结果:");
DemonstrateFastestResult();
// 3. 超时实现
Console.WriteLine("\n3. 超时实现:");
DemonstrateTimeoutImplementation();
Console.WriteLine("Task.WhenAny 基本使用演示完成\n");
}
private static void DemonstrateBasicWhenAny()
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
Task[] tasks = new Task[]
{
Task.Run(() =>
{
Console.WriteLine(" 慢任务开始 (3秒)");
Thread.Sleep(3000);
Console.WriteLine(" 慢任务完成");
}),
Task.Run(() =>
{
Console.WriteLine(" 快任务开始 (1秒)");
Thread.Sleep(1000);
Console.WriteLine(" 快任务完成");
}),
Task.Run(() =>
{
Console.WriteLine(" 中等任务开始 (2秒)");
Thread.Sleep(2000);
Console.WriteLine(" 中等任务完成");
})
};
// 等待任意一个任务完成
Task completedTask = Task.WhenAny(tasks).Result;
stopwatch.Stop();
Console.WriteLine($" 第一个完成的任务索引: {Array.IndexOf(tasks, completedTask)}");
Console.WriteLine($" 等待时间: {stopwatch.ElapsedMilliseconds}ms");
// 检查其他任务的状态
for (int i = 0; i < tasks.Length; i++)
{
Console.WriteLine($" 任务{i}状态: {tasks[i].Status}");
}
}
private static void DemonstrateFastestResult()
{
// 模拟从多个数据源获取数据
Task<string>[] dataSources = new Task<string>[]
{
FetchFromDataSource("数据库", 1500),
FetchFromDataSource("缓存", 300),
FetchFromDataSource("API", 1000),
FetchFromDataSource("文件", 800)
};
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// 获取最快的响应
Task<string> fastestTask = Task.WhenAny(dataSources).Result;
string fastestResult = fastestTask.Result;
stopwatch.Stop();
Console.WriteLine($" 最快的响应: {fastestResult}");
Console.WriteLine($" 响应时间: {stopwatch.ElapsedMilliseconds}ms");
// 显示其他数据源的状态
Console.WriteLine(" 其他数据源状态:");
for (int i = 0; i < dataSources.Length; i++)
{
var task = dataSources[i];
string status = task.IsCompleted ?
(task.IsCompletedSuccessfully ? "已完成" : "失败") : "进行中";
Console.WriteLine($" 数据源{i + 1}: {status}");
}
}
private static Task<string> FetchFromDataSource(string sourceName, int delay)
{
return Task.Run(() =>
{
Console.WriteLine($" 开始从{sourceName}获取数据...");
Thread.Sleep(delay);
string result = $"来自{sourceName}的数据";
Console.WriteLine($" {result} (耗时{delay}ms)");
return result;
});
}
private static void DemonstrateTimeoutImplementation()
{
var timeouts = new[] { 500, 1500, 2500 };
foreach (int timeoutMs in timeouts)
{
Console.WriteLine($"\n 测试 {timeoutMs}ms 超时:");
// 创建一个长时间运行的任务
Task<string> longTask = Task.Run(() =>
{
Console.WriteLine(" 长任务开始 (预计2秒)");
Thread.Sleep(2000);
return "长任务完成";
});
// 创建超时任务
Task timeoutTask = Task.Delay(timeoutMs);
// 等待第一个完成的任务
Task completedTask = Task.WhenAny(longTask, timeoutTask).Result;
if (completedTask == timeoutTask)
{
Console.WriteLine($" 操作超时 ({timeoutMs}ms)");
}
else
{
Console.WriteLine($" 操作完成: {longTask.Result}");
}
}
}
}
高级使用模式
public class AdvancedWhenAllAnyDemo
{
public static void DemonstrateAdvancedPatterns()
{
Console.WriteLine("=== 高级使用模式演示 ===");
// 1. 分批处理
Console.WriteLine("1. 分批处理:");
DemonstrateBatchProcessing().Wait();
// 2. 容错处理
Console.WriteLine("\n2. 容错处理:");
DemonstrateFaultTolerantProcessing().Wait();
// 3. 进度追踪
Console.WriteLine("\n3. 进度追踪:");
DemonstrateProgressTracking().Wait();
Console.WriteLine("高级使用模式演示完成\n");
}
private static async Task DemonstrateBatchProcessing()
{
// 模拟大量数据项
var dataItems = Enumerable.Range(1, 20).ToArray();
const int batchSize = 5;
Console.WriteLine($" 处理 {dataItems.Length} 个数据项,批次大小: {batchSize}");
var allResults = new List<string>();
// 分批处理
for (int i = 0; i < dataItems.Length; i += batchSize)
{
var batch = dataItems.Skip(i).Take(batchSize).ToArray();
Console.WriteLine($" 处理批次 {i / batchSize + 1}: 项目 {i + 1}-{Math.Min(i + batchSize, dataItems.Length)}");
// 并行处理当前批次
var batchTasks = batch.Select(item => ProcessDataItemAsync(item)).ToArray();
string[] batchResults = await Task.WhenAll(batchTasks);
allResults.AddRange(batchResults);
Console.WriteLine($" 批次完成,获得 {batchResults.Length} 个结果");
}
Console.WriteLine($" 所有批次完成,总共获得 {allResults.Count} 个结果");
}
private static async Task<string> ProcessDataItemAsync(int item)
{
// 模拟数据处理
await Task.Delay(200);
return $"已处理项目{item}";
}
private static async Task DemonstrateFaultTolerantProcessing()
{
// 创建一些可能失败的任务
var tasks = new[]
{
CreateReliableTask("任务A", 300, 0.1), // 10% 失败率
CreateReliableTask("任务B", 500, 0.3), // 30% 失败率
CreateReliableTask("任务C", 400, 0.0), // 不会失败
CreateReliableTask("任务D", 600, 0.5), // 50% 失败率
CreateReliableTask("任务E", 350, 0.2) // 20% 失败率
};
Console.WriteLine(" 启动容错任务处理...");
var successfulResults = new List<string>();
var failedTasks = new List<string>();
try
{
// 等待所有任务完成(忽略异常)
await Task.WhenAll(tasks.Select(async task =>
{
try
{
string result = await task;
lock (successfulResults)
{
successfulResults.Add(result);
}
}
catch (Exception ex)
{
lock (failedTasks)
{
failedTasks.Add($"失败: {ex.Message}");
}
}
}));
}
catch
{
// 忽略外层异常,我们已经在内部处理了
}
Console.WriteLine($" 处理完成:");
Console.WriteLine($" 成功: {successfulResults.Count} 个");
Console.WriteLine($" 失败: {failedTasks.Count} 个");
foreach (string result in successfulResults)
{
Console.WriteLine($" ✓ {result}");
}
foreach (string failure in failedTasks)
{
Console.WriteLine($" ✗ {failure}");
}
}
private static async Task<string> CreateReliableTask(string taskName, int delay, double failureRate)
{
await Task.Delay(delay);
if (new Random().NextDouble() < failureRate)
{
throw new Exception($"{taskName} 随机失败");
}
return $"{taskName} 成功完成";
}
private static async Task DemonstrateProgressTracking()
{
var tasks = new[]
{
CreateProgressTask("文件下载", 2000),
CreateProgressTask("数据处理", 1500),
CreateProgressTask("结果上传", 1800),
CreateProgressTask("邮件发送", 800),
CreateProgressTask("日志记录", 600)
};
Console.WriteLine($" 开始追踪 {tasks.Length} 个任务的进度...");
var completedTasks = new List<Task>();
var remainingTasks = tasks.ToList();
while (remainingTasks.Any())
{
// 等待下一个任务完成
Task completedTask = await Task.WhenAny(remainingTasks);
completedTasks.Add(completedTask);
remainingTasks.Remove(completedTask);
// 报告进度
int completedCount = completedTasks.Count;
int totalCount = tasks.Length;
int progressPercent = (completedCount * 100) / totalCount;
Console.WriteLine($" 进度: {completedCount}/{totalCount} ({progressPercent}%) " +
$"- 最新完成: {await completedTask}");
}
Console.WriteLine(" 所有任务完成!");
}
private static async Task<string> CreateProgressTask(string taskName, int duration)
{
await Task.Delay(duration);
return taskName;
}
}
异常处理模式
public class ExceptionHandlingDemo
{
public static void DemonstrateExceptionHandling()
{
Console.WriteLine("=== 异常处理模式演示 ===");
// 1. WhenAll 的异常处理
Console.WriteLine("1. WhenAll 的异常处理:");
DemonstrateWhenAllExceptions().Wait();
// 2. WhenAny 的异常处理
Console.WriteLine("\n2. WhenAny 的异常处理:");
DemonstrateWhenAnyExceptions().Wait();
// 3. 混合异常处理
Console.WriteLine("\n3. 混合异常处理:");
DemonstrateMixedExceptionHandling().Wait();
Console.WriteLine("异常处理模式演示完成\n");
}
private static async Task DemonstrateWhenAllExceptions()
{
var tasks = new[]
{
CreateTaskWithPossibleException("任务A", 500, false),
CreateTaskWithPossibleException("任务B", 300, true), // 会失败
CreateTaskWithPossibleException("任务C", 700, false),
CreateTaskWithPossibleException("任务D", 400, true) // 会失败
};
try
{
string[] results = await Task.WhenAll(tasks);
Console.WriteLine(" 所有任务成功完成:");
foreach (string result in results)
{
Console.WriteLine($" {result}");
}
}
catch (Exception ex)
{
Console.WriteLine($" WhenAll 捕获到异常: {ex.Message}");
// 检查每个任务的详细状态
Console.WriteLine(" 详细任务状态:");
for (int i = 0; i < tasks.Length; i++)
{
var task = tasks[i];
if (task.IsCompletedSuccessfully)
{
Console.WriteLine($" 任务{i + 1}: 成功 - {task.Result}");
}
else if (task.IsFaulted)
{
Console.WriteLine($" 任务{i + 1}: 失败 - {task.Exception?.InnerException?.Message}");
}
else if (task.IsCanceled)
{
Console.WriteLine($" 任务{i + 1}: 已取消");
}
else
{
Console.WriteLine($" 任务{i + 1}: {task.Status}");
}
}
}
}
private static async Task<string> CreateTaskWithPossibleException(string taskName, int delay, bool shouldFail)
{
await Task.Delay(delay);
if (shouldFail)
{
throw new InvalidOperationException($"{taskName} 故意失败");
}
return $"{taskName} 成功";
}
private static async Task DemonstrateWhenAnyExceptions()
{
var tasks = new[]
{
CreateTaskWithPossibleException("快速失败任务", 200, true),
CreateTaskWithPossibleException("慢速成功任务", 1000, false),
CreateTaskWithPossibleException("中速失败任务", 600, true)
};
try
{
Task<string> completedTask = await Task.WhenAny(tasks);
// 检查完成的任务是否成功
if (completedTask.IsCompletedSuccessfully)
{
Console.WriteLine($" 第一个完成的任务成功: {completedTask.Result}");
}
else if (completedTask.IsFaulted)
{
Console.WriteLine($" 第一个完成的任务失败: {completedTask.Exception?.InnerException?.Message}");
}
}
catch (Exception ex)
{
Console.WriteLine($" WhenAny 异常: {ex.Message}");
}
// 等待一段时间,让其他任务也完成
await Task.Delay(1200);
Console.WriteLine(" 所有任务最终状态:");
for (int i = 0; i < tasks.Length; i++)
{
var task = tasks[i];
string status = task.IsCompletedSuccessfully ? "成功" :
task.IsFaulted ? "失败" :
task.IsCanceled ? "取消" : task.Status.ToString();
Console.WriteLine($" 任务{i + 1}: {status}");
}
}
private static async Task DemonstrateMixedExceptionHandling()
{
Console.WriteLine(" 实现任务结果收集器...");
var tasks = new[]
{
CreateTaskWithPossibleException("API调用1", 300, false),
CreateTaskWithPossibleException("API调用2", 500, true),
CreateTaskWithPossibleException("API调用3", 400, false),
CreateTaskWithPossibleException("API调用4", 600, true),
CreateTaskWithPossibleException("API调用5", 350, false)
};
var results = new List<string>();
var errors = new List<string>();
// 为每个任务包装异常处理
var wrappedTasks = tasks.Select(async (task, index) =>
{
try
{
string result = await task;
lock (results)
{
results.Add($"API{index + 1}: {result}");
}
}
catch (Exception ex)
{
lock (errors)
{
errors.Add($"API{index + 1}: {ex.Message}");
}
}
});
// 等待所有包装任务完成
await Task.WhenAll(wrappedTasks);
Console.WriteLine($" 收集完成:");
Console.WriteLine($" 成功结果: {results.Count} 个");
foreach (string result in results)
{
Console.WriteLine($" ✓ {result}");
}
Console.WriteLine($" 错误结果: {errors.Count} 个");
foreach (string error in errors)
{
Console.WriteLine($" ✗ {error}");
}
}
}
实际应用场景
public class PracticalApplicationsDemo
{
public class WebScrapingManager
{
public async Task<string[]> ScrapeMultipleUrlsAsync(string[] urls, int maxConcurrent = 3)
{
Console.WriteLine($"开始抓取 {urls.Length} 个URL,最大并发: {maxConcurrent}");
var results = new List<string>();
// 分批处理,控制并发数
for (int i = 0; i < urls.Length; i += maxConcurrent)
{
var batch = urls.Skip(i).Take(maxConcurrent).ToArray();
Console.WriteLine($" 处理批次 {i / maxConcurrent + 1}: {batch.Length} 个URL");
var batchTasks = batch.Select(url => ScrapeUrlAsync(url)).ToArray();
try
{
string[] batchResults = await Task.WhenAll(batchTasks);
results.AddRange(batchResults);
Console.WriteLine($" 批次完成,获得 {batchResults.Length} 个结果");
}
catch (Exception ex)
{
Console.WriteLine($" 批次失败: {ex.Message}");
// 逐个检查任务结果
foreach (var task in batchTasks)
{
if (task.IsCompletedSuccessfully)
{
results.Add(task.Result);
}
}
}
}
return results.ToArray();
}
private async Task<string> ScrapeUrlAsync(string url)
{
await Task.Delay(500 + new Random().Next(1000)); // 模拟网络延迟
// 模拟偶尔的失败
if (new Random().Next(5) == 0)
{
throw new Exception($"无法访问 {url}");
}
return $"来自 {url} 的内容";
}
}
public class LoadBalancer
{
public async Task<T> GetFastestResponseAsync<T>(Func<Task<T>>[] serviceCallFactories)
{
Console.WriteLine($"向 {serviceCallFactories.Length} 个服务发送请求...");
// 创建所有服务调用任务
var tasks = serviceCallFactories.Select((factory, index) =>
CallServiceWithLogging(factory, index)).ToArray();
// 等待第一个成功的响应
while (tasks.Any(t => !t.IsCompleted))
{
Task<T> completedTask = await Task.WhenAny(tasks);
if (completedTask.IsCompletedSuccessfully)
{
Console.WriteLine(" 获得第一个成功响应");
return completedTask.Result;
}
else
{
Console.WriteLine(" 一个服务调用失败,继续等待其他服务...");
// 从待等待任务中移除失败的任务
tasks = tasks.Where(t => t != completedTask && !t.IsCompleted).ToArray();
}
}
throw new Exception("所有服务调用都失败了");
}
private async Task<T> CallServiceWithLogging<T>(Func<Task<T>> serviceCallFactory, int serviceIndex)
{
try
{
Console.WriteLine($" 服务{serviceIndex + 1} 开始调用");
T result = await serviceCallFactory();
Console.WriteLine($" 服务{serviceIndex + 1} 调用成功");
return result;
}
catch (Exception ex)
{
Console.WriteLine($" 服务{serviceIndex + 1} 调用失败: {ex.Message}");
throw;
}
}
}
public static void DemonstratePracticalApplications()
{
Console.WriteLine("=== 实际应用场景演示 ===");
// 1. Web 抓取管理器
Console.WriteLine("1. Web 抓取管理器:");
DemonstrateWebScraping().Wait();
// 2. 负载均衡器
Console.WriteLine("\n2. 负载均衡器:");
DemonstrateLoadBalancer().Wait();
// 3. 数据聚合服务
Console.WriteLine("\n3. 数据聚合服务:");
DemonstrateDataAggregation().Wait();
Console.WriteLine("实际应用场景演示完成\n");
}
private static async Task DemonstrateWebScraping()
{
var scraper = new WebScrapingManager();
var urls = new[]
{
"http://site1.com", "http://site2.com", "http://site3.com",
"http://site4.com", "http://site5.com", "http://site6.com",
"http://site7.com"
};
try
{
string[] results = await scraper.ScrapeMultipleUrlsAsync(urls, maxConcurrent: 3);
Console.WriteLine($"抓取完成,获得 {results.Length} 个结果:");
foreach (string result in results.Take(3)) // 只显示前3个
{
Console.WriteLine($" {result}");
}
if (results.Length > 3)
{
Console.WriteLine($" ... 还有 {results.Length - 3} 个结果");
}
}
catch (Exception ex)
{
Console.WriteLine($"抓取失败: {ex.Message}");
}
}
private static async Task DemonstrateLoadBalancer()
{
var loadBalancer = new LoadBalancer();
// 模拟多个服务
Func<Task<string>>[] services = new Func<Task<string>>[]
{
() => SimulateServiceCall("服务A", 1200, 0.3), // 慢但相对可靠
() => SimulateServiceCall("服务B", 800, 0.5), // 中等速度,经常失败
() => SimulateServiceCall("服务C", 400, 0.7), // 快但不可靠
() => SimulateServiceCall("服务D", 600, 0.2) // 较快且可靠
};
try
{
string result = await loadBalancer.GetFastestResponseAsync(services);
Console.WriteLine($"负载均衡结果: {result}");
}
catch (Exception ex)
{
Console.WriteLine($"负载均衡失败: {ex.Message}");
}
}
private static async Task<string> SimulateServiceCall(string serviceName, int delay, double failureRate)
{
await Task.Delay(delay);
if (new Random().NextDouble() < failureRate)
{
throw new Exception($"{serviceName} 不可用");
}
return $"来自{serviceName}的响应";
}
private static async Task DemonstrateDataAggregation()
{
Console.WriteLine("聚合多个数据源的信息...");
// 模拟从不同数据源获取数据
var dataTasks = new[]
{
GetUserProfile("用户基本信息"),
GetUserPreferences("用户偏好"),
GetUserActivity("用户活动"),
GetUserStats("用户统计")
};
try
{
string[] dataResults = await Task.WhenAll(dataTasks);
Console.WriteLine("数据聚合完成:");
foreach (string data in dataResults)
{
Console.WriteLine($" ✓ {data}");
}
// 组合所有数据
string aggregatedData = string.Join(" | ", dataResults);
Console.WriteLine($"\n聚合结果: {aggregatedData}");
}
catch (Exception ex)
{
Console.WriteLine($"数据聚合失败: {ex.Message}");
// 尝试获取部分数据
var partialResults = new List<string>();
foreach (var task in dataTasks)
{
if (task.IsCompletedSuccessfully)
{
partialResults.Add(task.Result);
}
}
if (partialResults.Any())
{
Console.WriteLine($"获得部分数据: {string.Join(" | ", partialResults)}");
}
}
}
private static async Task<string> GetUserProfile(string dataType)
{
await Task.Delay(300);
return dataType;
}
private static async Task<string> GetUserPreferences(string dataType)
{
await Task.Delay(500);
return dataType;
}
private static async Task<string> GetUserActivity(string dataType)
{
await Task.Delay(400);
return dataType;
}
private static async Task<string> GetUserStats(string dataType)
{
await Task.Delay(600);
return dataType;
}
}
综合演示
public class ComprehensiveWhenAllAnyDemo
{
public static void RunAllDemos()
{
Console.WriteLine("Task.WhenAll 和 Task.WhenAny 综合演示");
Console.WriteLine("=".PadRight(60, '='));
// 1. Task.WhenAll 基本使用
WhenAllBasicDemo.DemonstrateWhenAllBasic();
// 2. Task.WhenAny 基本使用
WhenAnyBasicDemo.DemonstrateWhenAnyBasic();
// 3. 高级使用模式
AdvancedWhenAllAnyDemo.DemonstrateAdvancedPatterns();
// 4. 异常处理模式
ExceptionHandlingDemo.DemonstrateExceptionHandling();
// 5. 实际应用场景
PracticalApplicationsDemo.DemonstratePracticalApplications();
Console.WriteLine("所有 WhenAll/WhenAny 演示完成");
}
}
总结
Task.WhenAll 的核心特点
- 并行执行:所有任务同时开始,并行执行
- 等待全部完成:必须等待所有任务都完成才返回
- 结果聚合:自动收集所有任务的返回值到数组中
- 异常行为:任何一个任务失败都会导致整体失败,但会等待所有任务完成
Task.WhenAny 的核心特点
- 竞争执行:等待第一个完成的任务
- 快速响应:一旦有任务完成就立即返回
- 结果选择:返回第一个完成的任务,需要手动获取结果
- 异常独立:只关心第一个完成的任务的状态
性能优势对比
- WhenAll vs 逐个等待:WhenAll 允许任务并行执行,总时间等于最慢任务的时间
- WhenAny vs 轮询检查:WhenAny 使用高效的事件机制,避免了轮询开销
- 内存效率:两者都比手动管理任务状态更节省内存
异常处理策略
- WhenAll 异常:第一个异常会被抛出,但可以检查所有任务的详细状态
- WhenAny 异常:需要手动检查完成任务的状态
- 容错处理:通过包装任务来实现容错逻辑
- 部分成功:在某些场景下可以接受部分任务失败
最佳实践建议
- 选择合适的方法:根据业务需求选择 WhenAll 或 WhenAny
- 控制并发数:使用分批处理控制并发任务数量
- 异常处理:根据业务需要决定是否容忍部分失败
- 资源管理:及时处理完成的任务,避免资源泄漏
常见应用场景
- WhenAll 场景:数据聚合、批量处理、并行计算
- WhenAny 场景:超时实现、负载均衡、冗余处理
- 组合使用:复杂业务流程中两者可以组合使用
- 监控和诊断:进度追踪、性能监控、故障诊断
注意事项
- 任务生命周期:WhenAny 完成后其他任务仍在运行
- 取消传播:确保取消令牌正确传播到所有任务
- 内存考虑:长时间运行的任务可能导致内存积累
- 调试复杂性:并行任务的调试比顺序执行更复杂