如何在不同返回类型的异步任务完成时分别处理结果?
处理不同返回类型的异步任务:完成即处理结果
针对不同返回类型的异步任务,要实现并发执行且完成后立即处理结果,有几种简洁的实现方式:
方案一:分别await已启动的任务
先启动所有任务让它们并发运行,之后逐个await每个任务,任务完成后立即处理结果。这种方式代码简单,适合任务数量不多的场景:
private async Task CompleteTasksAsync() { // 先启动所有任务,触发并发执行 var taskA = GetStringAsync(); var taskB = GetIntAsync(); var taskC = GetStringListAsync(); var taskD = GetGenericAsync<double>(1d); // 逐个等待任务完成,完成后立即处理结果 Console.WriteLine(await taskA); Console.WriteLine(await taskB); var listResult = await taskC; Console.WriteLine($"列表内容:{string.Join(", ", listResult)}"); Console.WriteLine(await taskD); } private Task<string> GetStringAsync() => Task.FromResult("string"); private Task<int> GetIntAsync() => Task.FromResult(1); private Task<List<string>> GetStringListAsync() => Task.FromResult(new List<string> { "string" }); private Task<T> GetGenericAsync<T>(T data) => Task.FromResult(data);
所有任务在初始化阶段就已并发执行,后续的await只是等待对应任务的结果,若任务已提前完成则直接获取结果处理,不会额外阻塞。
方案二:按任务完成顺序处理(Task.WhenAny循环)
如果需要严格按照任务实际完成的先后顺序处理结果,可使用Task.WhenAny循环监听,每次处理刚完成的任务:
private async Task CompleteTasksAsync() { var tasks = new HashSet<Task> { GetStringAsync(), GetIntAsync(), GetStringListAsync(), GetGenericAsync<double>(1d) }; while (tasks.Count > 0) { var completedTask = await Task.WhenAny(tasks); tasks.Remove(completedTask); // 根据任务类型匹配处理逻辑 if (completedTask is Task<string> stringTask) Console.WriteLine(stringTask.Result); else if (completedTask is Task<int> intTask) Console.WriteLine(intTask.Result); else if (completedTask is Task<List<string>> listTask) Console.WriteLine($"列表内容:{string.Join(", ", listTask.Result)}"); else if (completedTask is Task<double> doubleTask) Console.WriteLine(doubleTask.Result); } } private Task<string> GetStringAsync() => Task.FromResult("string"); private Task<int> GetIntAsync() => Task.FromResult(1); private Task<List<string>> GetStringListAsync() => Task.FromResult(new List<string> { "string" }); private Task<T> GetGenericAsync<T>(T data) => Task.FromResult(data);
这种方式会持续监控未完成任务,一旦有任务完成就立即处理,完全遵循任务实际完成的先后顺序。
方案三:绑定任务与处理逻辑(通用包装)
通过通用方法将每个任务和对应的处理逻辑绑定,避免后续类型判断,代码更简洁:
private async Task CompleteTasksAsync() { var processingTasks = new List<Task> { HandleTask(GetStringAsync(), result => Console.WriteLine(result)), HandleTask(GetIntAsync(), result => Console.WriteLine(result)), HandleTask(GetStringListAsync(), result => Console.WriteLine($"列表内容:{string.Join(", ", result)}")), HandleTask(GetGenericAsync<double>(1d), result => Console.WriteLine(result)) }; await Task.WhenAll(processingTasks); } // 通用包装方法:等待任务完成后执行处理逻辑 private async Task HandleTask<T>(Task<T> task, Action<T> handler) { var result = await task; handler(result); } private Task<string> GetStringAsync() => Task.FromResult("string"); private Task<int> GetIntAsync() => Task.FromResult(1); private Task<List<string>> GetStringListAsync() => Task.FromResult(new List<string> { "string" }); private Task<T> GetGenericAsync<T>(T data) => Task.FromResult(data);
每个任务在完成后会自动触发对应的处理逻辑,最后用Task.WhenAll等待所有处理流程结束即可。
内容的提问来源于stack exchange,提问作者ARH
相关产品推荐
相关产品推荐

