C# WinForm如何等待所有并行任务执行完毕后再运行后续逻辑
问题原因分析与解决方案
你的代码出现提前触发完成逻辑的核心原因是startTask方法使用了async void作为返回值:
- async void方法仅适用于UI事件处理程序,无法被
await正确等待执行完成 - 当你调用
await Task.Run(() => startTask(...))时,Task.Run只会等到startTask内部的await Task.Run(() => doJob(...))第一次挂起就认为任务已经结束,不会等待doJob的所有逻辑(包括removeEmptyFolder)执行完毕
修复方案
你采取的修改方式是正确的,直接去掉多余的startTask包装,直接在Task.Run中执行doJob方法即可,修改后的核心逻辑如下:
foreach (var item in this.listBox1.Items) { if (Directory.Exists((string)item)) { // 直接等待doJob执行完成,没有多余的async void包装 await Task.Run(() => doJob((string)item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex)); } } FinishedTask();
额外优化建议
你可以顺便核对doJob方法的语法结构,你贴出的代码里Parallel.ForEach执行完后多了一个闭合大括号,会导致后面的删除空文件夹逻辑不在doJob方法体内,修正后参考代码:
public static void doJob(string directory,bool removeOtherFlag, int worker) { // 遍历目录 createFolders(directory); // 按扩展名创建分类文件夹 string[] all_files = Directory.GetFiles(directory); Parallel.ForEach(all_files, new ParallelOptions { MaxDegreeOfParallelism = worker }, (item) => multiprocessingFiles(item)); // 下面的逻辑要放在doJob的大括号内 if(removeOtherFlag == true) deleteOtherFolder(Path.Combine(directory,"other")); removeEmptyFolder(directory); // 删除空的扩展名分类文件夹 }
内容的提问来源于stack exchange,提问作者J. Sumittanun
相关产品推荐
相关产品推荐

