C#中如何条件性执行并行任务?解决未赋值及Created状态问题
处理C#条件性并行任务的正确方式
问题根源
你遇到的问题有两个核心点:
- 不进入
if分支时,ccTask、cfTask未赋值,会触发编译错误或运行时空引用异常。 - 用
new Task<T>创建的任务处于Created状态,未自动启动,会导致Task.WhenAll无限等待。
解决方案一:提前初始化默认已完成任务
最简洁高效的方式是在声明变量时直接赋值为已完成的任务,无需额外else分支,从根源避免未赋值问题:
// 初始化默认的已完成任务,确保变量始终有有效值 Task<StandardResponse<bool>> qcTask = service.ProcessQuestionsAndComments(inputData); Task<StandardResponse<bool>> ccTask = Task.FromResult(new StandardResponse<bool> { Status = HttpStatusCode.OK }); Task<StandardResponse<bool>> cfTask = Task.FromResult(new StandardResponse<bool> { Status = HttpStatusCode.OK }); if (StatusId == (int)STATUS.COMPLETED) { // 覆盖默认任务,替换为实际需要并行执行的任务 ccTask = service.ProcessCompletedStatus(inputData); cfTask = service.ProcessCompletedFile(inputData); } await Task.WhenAll(qcTask, ccTask, cfTask).ConfigureAwait(false);
这种方式的优势:
- 代码结构更简洁,无需额外分支处理
Task.FromResult直接返回已完成的Task实例,性能开销极低- 彻底避免空引用和未赋值问题
解决方案二:在else分支中处理默认任务
如果坚持保留else分支,不要使用new Task<T>创建任务(它不会自动启动),推荐以下两种方式:
方式A:使用Task.FromResult(推荐)
Task<StandardResponse<bool>> qcTask; Task<StandardResponse<bool>> ccTask; Task<StandardResponse<bool>> cfTask; qcTask = service.ProcessQuestionsAndComments(inputData); if (StatusId == (int)STATUS.COMPLETED) { ccTask = service.ProcessCompletedStatus(inputData); cfTask = service.ProcessCompletedFile(inputData); } else { // 直接返回已完成任务,无需手动启动 ccTask = Task.FromResult(new StandardResponse<bool> { Status = HttpStatusCode.OK }); cfTask = Task.FromResult(new StandardResponse<bool> { Status = HttpStatusCode.OK }); } await Task.WhenAll(qcTask, ccTask, cfTask).ConfigureAwait(false);
方式B:手动启动new创建的任务(不推荐)
如果一定要用new Task<T>,必须手动调用Start()启动任务,否则任务永远不会执行:
else { ccTask = new Task<StandardResponse<bool>>(() => new StandardResponse<bool> { Status = HttpStatusCode.OK }); cfTask = new Task<StandardResponse<bool>>(() => new StandardResponse<bool> { Status = HttpStatusCode.OK }); // 必须手动启动任务,否则会处于Created状态 ccTask.Start(); cfTask.Start(); }
这种方式不推荐,因为Task.FromResult更简洁高效,new Task<T>通常用于高级任务调度场景,日常并行处理用前者更合适。
额外优化建议
如果条件性任务数量不固定,可以用List<Task>动态管理任务,扩展性更好:
var tasks = new List<Task<StandardResponse<bool>>>(); tasks.Add(service.ProcessQuestionsAndComments(inputData)); if (StatusId == (int)STATUS.COMPLETED) { tasks.Add(service.ProcessCompletedStatus(inputData)); tasks.Add(service.ProcessCompletedFile(inputData)); } else { tasks.Add(Task.FromResult(new StandardResponse<bool> { Status = HttpStatusCode.OK })); tasks.Add(Task.FromResult(new StandardResponse<bool> { Status = HttpStatusCode.OK })); } await Task.WhenAll(tasks).ConfigureAwait(false);
内容的提问来源于stack exchange,提问作者Kiran Ramchandra Parab
相关产品推荐
相关产品推荐

