2013-05-07 2 views
1

У меня есть список строк, содержащих около 20000 строк, каждый из которых длится 1000 символов. Я хочу заменить все эти строки на обратную версию той же строки в той же позиции, используя несколько фоновых работников.C# несколько фоновых работников, обращающихся к объекту

Вот что я делал до сих пор:

Настройка фона рабочих (8, потому что компьютер имеет 8 ядер)

for (int j = 0; j < 8; j++) 
    { 
    BackgroundWorker worker = new BackgroundWorker(); 
    worker.DoWork += DoWork; 
    worker.RunWorkerCompleted += WorkComplete; 
    worker.RunWorkerAsync(); 
    } 

Проблема, которую я имею, что я не знаю, что введите функцию doWork.

Если функция DoWork держать цикл, как это:

private void DoWork(object sender, DoWorkEventArgs e) 
{ 
    while(list.count > 0) 
    { 
     reverse and add to list 
    }   
} 

Или функция DoWork только сделать реверс и затем передать обратную строку в функции WorkComplete?

private void DoWork(object sender, DoWorkEventArgs e) 
    { 
     reverse string 
     r.result = reversed string 
    } 
+2

В качестве альтернативы фоновому работнику вы рассмотрели «параллельную библиотеку задач»? http://msdn.microsoft.com/en-us/library/dd460717.aspx –

+0

Как вы хотите отслеживать, какие элементы списка были обработаны другими экземплярами backgroundworker? – JeffRSon

+0

Это не совсем то, что делает фоновой рабочий (BGW). Обычно у вас есть одна BGW, и она не использует общие данные (кроме как в ходе и полных событиях). Если вы хотите, чтобы одновременно обрабатывали данные одновременно, я бы предложил использовать TPL и развернуть задачу. –

ответ

7

Я хотел бы предложить альтернативный подход к этому.

Вместо того, чтобы создавать несколько BackgroundWorkers, вы можете просто создать его и внутри его DoWork() вы можете использовать Parallel.ForEach() для изменения строк.

Таким образом, он будет обрабатывать количество потоков оптимально для вас.

Вам все равно нужно использовать BackgroundWorker, чтобы избежать блокировки потока пользовательского интерфейса.

Вот компилируемый пример работает в приложении консоли:

using System; 
using System.Linq; 
using System.Threading.Tasks; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main() 
     { 
      string[] data = Enumerable.Range(10000, 100).Select(i => i.ToString()).ToArray(); 

      Parallel.ForEach(data, (item, state, index) => data[index] = Reverse(item)); 

      foreach (var s in data) 
       Console.WriteLine(s); 
     } 

     public static string Reverse(string s) 
     { 
      char[] charArray = s.ToCharArray(); 
      Array.Reverse(charArray); 
      return new string(charArray); 
     } 
    } 
} 

Кроме того, если вы используете .NET 4.5 вы можете избежать использования BackgroundWorker полностью с помощью новой функции await/async.

Например, создайте приложение Windows Forms по умолчанию и нанесите на него надпись label1 и кнопку button1. Затем измените файл Form1.cs на:

using System; 
using System.Linq; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      data = Enumerable.Range(10000, 1000000).Select(i => i.ToString()).ToArray(); 
     } 

     async void button1_Click(object sender, EventArgs e) 
     { 
      label1.Text = "Reversing strings..."; 
      await doWork(); 
      label1.Text = "Reversed strings."; 
     } 

     Task doWork() 
     { 
      return Task.Factory.StartNew(() => Parallel.ForEach(data, (item, state, index) => data[index] = reverse(item))); 
     } 

     static string reverse(string s) 
     { 
      char[] charArray = s.ToCharArray(); 
      Array.Reverse(charArray); 
      return new string(charArray); 
     } 

     readonly string[] data; 
    } 
} 

При нажатии на кнопку, интерфейс будет оставаться отзывчивым, а струны перепутаны.

+0

wow спасибо за ваш пример, плохо попробуйте – BuildingJarl

+0

@ 686 Я ожидаю, что вам, возможно, придется немного почитать документацию, чтобы посмотреть, как это работает ... –

+0

Прохладно, похоже, это очень хорошее решение. Извините, я не могу голосовать, потому что у меня пока нет достаточного количества репутации. – BuildingJarl

2

Важно ли использовать BackgroundWorker? Использование TPL очень просто:

using System.Threading.Tasks; 

Parallel.For(0, strings.Length, i=> strings[i] = reversed string); 

TPL будет балансировать нагрузку для вас (по умолчанию, он использует имеющееся количество ваших процессорных ядер), и это также будет хорошо работать на другой машине, с разным количеством ядер ,

+0

спасибо за ответ, его не важно для меня использовать фона рабочего.Я просто хочу, чтобы задача была выполнена как можно быстрее. Я даю ему попробовать – BuildingJarl

Смежные вопросы