并行 forEach 搜索文件

Parallel forEach search file

我有一个包含2个列表框的程序,这个程序是基于搜索文件,然后与StopWatch比较使用AsyncAwait和TPL的区别...第一个列表框做使用 AsyncAwait 的函数(我不知道这是否是更好的方法,但它有效,请参阅下面的代码)

private async void button1_Click(object sender, EventArgs e)
{
    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();
            listBox1.Items.Add(s);
            await Task.Delay(1);
            btIniciar1.Enabled = false;
        }
    }
    btIniciar1.Enabled = true;
    stopWatch.Stop();
    TimeSpan ts = stopWatch.Elapsed;
    textBox1.Text = ts.ToString("mm\:ss\.ff") + (" minuts");
}

然后在我的第二个列表框中我卡住了,我不知道如何实现 Parallel.ForEach 来表现得像 async,更好的方法是什么?我找不到在这种情况下使用 TPL 来执行与我的第一个列表框相同的方法,你能帮我吗?

在您的示例代码中使用 async 毫无意义,因为它实际上并没有异步执行任何操作。如果要将同步代码包装在后台线程中,请使用 Task.Run.

关于Parallel.ForEach,您可以通过将其包装在Task.Run中来异步处理它:await Task.Run(() => Parallel.ForEach(...));

注意 parallel/background 个线程不能直接访问 UI 个元素。如果您想从 background/threadpool 线程更新 UI,您可以使用 IProgress<T>/Progress<T>

更新:

序列号如下:

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");
}

我终于解决了这个问题:

 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);
    }
 }