2015-02-24 47 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"); 
}