2015-02-24 57 views
2

我有一个程序包含2个列表框,这个程序是基于搜索文件,然后与StopWatch区别使用AsyncAwait和TPL ...第一个列表框使用AsyncAwait(I不知道这是否是更好的方式做,但它的工作原理,请参阅下面我的代码)并行for each搜索文件

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.ForEachasync一样,有什么更好的方法来做到这一点?在这种情况下,我无法找到使用TPL的方式来执行与我的第一个列表框相同的操作,请问您能帮助我吗?

+0

您是使用winforms还是WPF?此外,如果您只是想将文件列表添加到'listBox1'中,您的操作并不完全清楚。如果是这样,您的并行解决方案将会变得更慢,因为您一次只能有一个线程添加项目,每个人都必须等待。如果您正在做其他事情,ForEach可能会更好地工作,但您需要告诉我们您的ForEach会真正做什么。 – 2015-02-24 15:18:55

+0

我正在使用winforms – Dix 2015-02-24 15:20:34

+2

Parallel.ForEach会对此很糟糕,因为只有UI线程才能更新UI,所以您必须切换回此线程才能将文件实际添加到列表中。如果你真的必须尝试这种实验,最好从函数返回一个字符串数组(例如文件名)。 – samjudson 2015-02-24 15:23:06

回答

0

最后,我已经解决了这个问题,这样做:

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

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

关于Parallel.ForEach,您可以通过在Task.Run包裹它以异步方式对待它:await Task.Run(() => Parallel.ForEach(...));

注意,并行/后台线程不能直接访问UI元素。如果您想从后台/线程池线程更新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"); 
}