【发布时间】:2021-10-21 20:03:49
【问题描述】:
我是 C# 新手。我正在编写窗口表单,用于根据其扩展名对文件夹内的文件进行排序。 使用一个文件夹执行任务时可行,但我将其修改为从列表框中的多个项目执行。
private async void startBtn_Click(object sender, EventArgs e)
{
if (this.listBox1.Items.Count != 0)
{
this.statusLabel.ForeColor = Color.DodgerBlue;
this.statusLabel.Text = "Sorting";
this.startBtn.Enabled = false;
this.removeOtherCheck.Enabled = false;
this.workerCounter.Enabled = false;
foreach (var item in this.listBox1.Items)
{
if (Directory.Exists( (string)item ))
{
await Task.Run(() => startTask((string)item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex));
}
}
FinishedTask();
}
private async void startTask(string path, bool removeOtherFlag, int worker)
{
await Task.Run(() => doJob(path, removeOtherFlag, worker));
}
private void FinishedTask()
{
this.statusLabel.ForeColor = Color.LimeGreen;
this.statusLabel.Text = "Finished";
this.startBtn.Enabled = true;
this.removeOtherCheck.Enabled = true;
this.workerCounter.Enabled = true;
}
//this method are seperate but I put it here so you guy can see it
public static void doJob(string directory,bool removeOtherFlag, int worker)
{
// loop in directory
createFolders(directory); // create extension folder
string[] all_files = Directory.GetFiles(directory);
Parallel.ForEach(all_files, new ParallelOptions { MaxDegreeOfParallelism = worker }, (item) => multiprocessingFiles(item));
}
if(removeOtherFlag == true) deleteOtherFolder(Path.Combine(directory,"other"));
removeEmptyFolder(directory); // remove empty extension folder
}
我将解释我的任务。 首先我在进程启动时单击开始按钮,它将禁用所有按钮,然后循环列表框中的每个项目并对文件夹中的所有文件进行排序。 一切完成后,它会显示已完成的标签并启用所有按钮。
问题是,它会在 removeEmptyFolder() 执行此操作之前显示已完成的标签并重新启用所有按钮。
我尝试将 Parallel.forEach 更改为 Parallel.For 但它没有做我的事。
编辑 谢谢大家的回答。 感谢 Harald Coppoolse 的结论。 Paulo Morgado 是对的。
我删除 startTask 并更改
await Task.Run(() => startTask((string)item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex));
到
await Task.Run(() => doJob(item, this.removeOtherCheck.Checked, this.workerCounter.TabIndex));
现在一切都如我所愿。 谢谢大家。
【问题讨论】:
-
multiprocessingFiles、deleteOtherFolder和removeEmptyFolder的实现是什么?它们是异步的吗? -
使用
Parallel.ForEach确实不太可能提高代码运行的速度。访问磁盘比对一堆字符串进行排序要慢几个数量级。除非执行的工作比排序多。 -
deleteOtherFolder,removeEmptyFolder 不是异步的,需要等到 parallel.ForEach 完成
-
您需要向我们展示
multiprocessingFiles方法。附带说明一下,C# 中的方法名称遵循 PascalCase 模式。MultiprocessingFiles是正确的。 -
没关系,这是您的问题:
private async void startTask。 Avoid async void.
标签: c# winforms async-await c#-7.0 c#-7.2