献丑贴:Task.Run中foreach优化
有一个场景:
在Task.Run中循环执行N个任务,原来的写法:
var task = Task.Run(async () => { int i = 0; foreach (var item in tables) { i++; await writefileAsync(namespace1, item, showProcess); } }); _ = task.ContinueWith(t => { stopwatch.Stop(); MessageBox.Show($"代码生成完毕!{stopwatch.Elapsed}"); });
这种写法其实最大的问题是,既然用了taks.run,而又手动进行循环顺序处理,其实并没有发挥出task的威力来,因为task是支持多个任务并行处理的,改用并行处理:
方法一:
var tasks = tables.Select(item => writefileAsync(namespace1, item, showProcess)); await Task.WhenAll(tasks); stopwatch.Stop(); MessageBox.Show($"代码生成完毕!{stopwatch.Elapsed}");
经过对比发现,性能提升明显(单次测试处理时间:0.9s->0.4s)!
方法2:采用Parallel.ForEachAsync(最优解)
await Parallel.ForEachAsync(tables, new ParallelOptions { MaxDegreeOfParallelism = 3 }, async (item, cancellationToken) => { await writefileAsync(namespace1, item, showProcess); }); stopwatch.Stop(); MessageBox.Show($"代码生成完毕!{stopwatch.Elapsed}");
性能进一步提升!~
方法3:Parallel.ForEach
int completed = 0; IProgress<int> progress = new Progress<int>(value => { this.progressBar1.Value = value; });var result = Parallel.ForEach(tables, item => { writefile(namespace1, item); // 线程安全地更新进度 int current = Interlocked.Increment(ref completed); progress.Report(current); }); if (result.IsCompleted == true) { stopwatch.Stop(); MessageBox.Show($"代码生成完毕!{stopwatch.Elapsed}"); }
浙公网安备 33010602011771号