C# 并行forEach搜索文件
我有一个包含2个列表框的程序,该程序基于搜索文件,然后与秒表比较使用AsyncWait和TPL的区别。。。第一个列表框使用C# 并行forEach搜索文件,c#,winforms,async-await,parallel.foreach,C#,Winforms,Async Await,Parallel.foreach,我有一个包含2个列表框的程序,该程序基于搜索文件,然后与秒表比较使用AsyncWait和TPL的区别。。。第一个列表框使用asyncwait(我不知道这是否是更好的方法,但它可以工作,请参阅下面的代码) 然后在我的第二个列表框中,我被卡住了,我不知道如何实现并行?在本例中,我找不到使用TPL的方法来实现与我的第一个列表框相同的功能,您能帮助我吗?在示例代码中使用async没有任何意义,因为它实际上没有异步执行任何操作。如果要将同步代码包装到后台线程中,请使用Task.Run 关于Parallel
asyncwait
(我不知道这是否是更好的方法,但它可以工作,请参阅下面的代码)
然后在我的第二个列表框中,我被卡住了,我不知道如何实现
并行?在本例中,我找不到使用TPL的方法来实现与我的第一个列表框相同的功能,您能帮助我吗?在示例代码中使用async
没有任何意义,因为它实际上没有异步执行任何操作。如果要将同步代码包装到后台线程中,请使用Task.Run
关于Parallel.ForEach
,您可以通过将其包装在Task.Run
:wait Task.Run(()=>Parallel.ForEach(…))中来异步处理它代码>
请注意,并行/后台线程不能直接访问UI元素。如果要从后台/线程池线程更新UI,可以使用IProgress
/Progress
更新:
串行代码如下所示:
private async void button1_Click(object sender, EventArgs e)
{
IProgress<string> progress = new Progress<string>(update =>
{
listBox1.Items.Add(s);
btIniciar1.Enabled = false;
});
var ts = await Task.Run(() =>
{
Stopwatch stopWatch = new Stopwatch();
foreach (string d in Directory.GetDirectories(@"C:\Visual Studio Projectes\Hash\AsyncAwait\Carpetes"))
{
foreach (string s in Directory.GetFiles(d))
{
stopWatch.Start();
progress.Report(s);
}
}
stopWatch.Stop();
return stopWatch.Elapsed;
});
btIniciar1.Enabled = true;
textBox1.Text = ts.ToString("mm\\:ss\\.ff") + (" minuts");
}
private async void button1_Click(object sender, EventArgs e)
{
IProgress<string> progress = new Progress<string>(update =>
{
listBox1.Items.Add(s);
btIniciar1.Enabled = false;
});
var ts = await Task.Run(() => Parallel.ForEach( ...
));
btIniciar1.Enabled = true;
textBox1.Text = ts.ToString("mm\\:ss\\.ff") + (" minuts");
}
private async void按钮1\u单击(对象发送方,事件参数e)
{
i进度=新进度(更新=>
{
列表框1.项目。添加;
btIniciar1.Enabled=false;
});
var ts=等待任务。运行(()=>
{
秒表秒表=新秒表();
foreach(Directory.GetDirectories(@“C:\Visual Studio Projectes\Hash\AsyncWait\地毯”)中的字符串d)
{
foreach(Directory.GetFiles(d)中的字符串s))
{
秒表。开始();
进度报告;
}
}
秒表;
返回秒表。已过;
});
btIniciar1.Enabled=true;
textBox1.Text=ts.ToString(“mm\\:ss\\.ff”)+(“minuts”);
}
并行代码如下所示:
private async void button1_Click(object sender, EventArgs e)
{
IProgress<string> progress = new Progress<string>(update =>
{
listBox1.Items.Add(s);
btIniciar1.Enabled = false;
});
var ts = await Task.Run(() =>
{
Stopwatch stopWatch = new Stopwatch();
foreach (string d in Directory.GetDirectories(@"C:\Visual Studio Projectes\Hash\AsyncAwait\Carpetes"))
{
foreach (string s in Directory.GetFiles(d))
{
stopWatch.Start();
progress.Report(s);
}
}
stopWatch.Stop();
return stopWatch.Elapsed;
});
btIniciar1.Enabled = true;
textBox1.Text = ts.ToString("mm\\:ss\\.ff") + (" minuts");
}
private async void button1_Click(object sender, EventArgs e)
{
IProgress<string> progress = new Progress<string>(update =>
{
listBox1.Items.Add(s);
btIniciar1.Enabled = false;
});
var ts = await Task.Run(() => Parallel.ForEach( ...
));
btIniciar1.Enabled = true;
textBox1.Text = ts.ToString("mm\\:ss\\.ff") + (" minuts");
}
private async void按钮1\u单击(对象发送方,事件参数e)
{
i进度=新进度(更新=>
{
列表框1.项目。添加;
btIniciar1.Enabled=false;
});
var ts=wait Task.Run(()=>Parallel.ForEach(。。。
));
btIniciar1.Enabled=true;
textBox1.Text=ts.ToString(“mm\\:ss\\.ff”)+(“minuts”);
}
最后,我通过以下方式解决了此问题:
DirectoryInfo nodeDir = new DirectoryInfo(@"c:\files");
Parallel.ForEach(nodeDir.GetDirectories(), async dir =>
{
foreach (string s in Directory.GetFiles(dir.FullName))
{
Invoke(new MethodInvoker(delegate { lbxParallel.Items.Add(s); }));
contador++;
await Task.Delay(1);
}
}
您使用的是winforms还是WPF?此外,还不清楚您想做什么,如果您只是想将文件列表添加到listBox1
,那么您的并行解决方案会更慢,因为一次只能有一个线程添加项目,每个人都必须等待轮到您。如果您正在做其他事情,ForEach可能会更好,但您需要向我们展示ForEach的真正功能。Parallel.ForEach对此不好,因为只有UI线程可以更新UI,因此您必须更改回该线程,以便将文件实际添加到列表中。如果您确实必须尝试这种实验,最好从函数返回字符串数组(例如文件名)。