2015-02-24 5 views
2

У меня есть программа, которая содержит 2 списка, эта программа басирована для поиска файла, а затем сравнивается с StopWatch разницей в использовании AsyncAwait и TPL ... В первом списке используется функция с использованием AsyncAwait (I не знаю, если это лучший способ сделать это, но это работает, см мой код ниже)Параллельный для каждого файла поиска

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

а потом в моей второй ListBox, где я застрял, я не знаю, как реализовать Parallel.ForEach действовать как async, что лучший способ сделать это? Я не могу найти способ использовать TPL в этом случае, чтобы сделать то же самое, что и мой первый список, не могли бы вы мне помочь?

+0

Вы используете winforms или WPF? Также не совсем ясно, что вы пытаетесь сделать, если вы просто пытаетесь добавить список файлов в 'listBox1'. Если это так, ваше параллельное решение будет медленнее, потому что вы можете иметь только один поток, добавляющий элементы одновременно и каждый должен будет ждать своей очереди. Если вы делаете что-то еще, то ForEach может работать лучше, но вы должны показать нам, что действительно сделает ваш ForEach. –

+0

Я использую winforms – Dix

+2

Parallel.ForEach был бы плохим для этого, так как только поток пользовательского интерфейса может обновлять пользовательский интерфейс, поэтому вам нужно будет вернуться к этому потоку, чтобы фактически добавить файл в список. Лучше вернуть массив строк (например, имена файлов) из функции, если вы действительно должны попробовать этот эксперимент. – samjudson

ответ

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(...));

Обратите внимание, что параллельные/фоновые потоки не могут напрямую получить доступ к элементам пользовательского интерфейса. Вы можете использовать IProgress<T>/Progress<T>, если вы хотите обновить интерфейс пользователя из потока background/threadpool.

Update:

Серийный код будет выглядеть следующим образом:

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"); 
} 
Смежные вопросы