2013-05-07 52 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

作爲背景工作者的替代方案,您是否看過「Task Parallel Library」? http://msdn.microsoft.com/en-us/library/dd460717.aspx – 2013-05-07 10:10:19

+0

你想如何跟蹤哪些列表項已被其他backgroundworker實例處理? – JeffRSon 2013-05-07 10:11:03

+0

這不是真正的背景工作者(BGW)設計的目的。您通常擁有一個BGW,並且不使用共享數據(除了進度和完成事件之外)。如果你想同時處理多個數據,我建議使用TPL並啓動一個任務。 – 2013-05-07 13:21:10

回答

7

我只是想建議一個替代方法。

與其創建多個BackgroundWorkers,您可以創建一個並在其DoWork()內部使用Parallel.ForEach()來反轉字符串。

這樣,它會爲您處理最佳線程數。

您仍然需要使用BackgroundWorker來避免鎖定UI線程。

下面是一個控制檯應用程序運行的編譯例子:

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窗體應用程序並在其上放置一個名爲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; 
    } 
} 

當您單擊該按鈕時,UI將保持響應而字符串反轉。

+0

哇感謝你的例子生病給我試一試 – BuildingJarl 2013-05-07 10:51:51

+0

@ 686我希望你可能需要閱讀一些文檔,看看它是如何工作的... – 2013-05-07 10:55:31

+0

酷似乎是一個非常好的解決方案對不起,我不能投票,因爲我還沒有足夠的代表。 – BuildingJarl 2013-05-07 13:09:43

2

使用BackgroundWorker對您來說至關重要嗎?使用TPL很簡單:

using System.Threading.Tasks; 

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

TPL將平衡你的負荷(默認情況下,它使用您的CPU內核的空房數),而這也將工作做好其他機器上,用不同量的核心。

+0

感謝您的回覆,它對我使用後臺工作人員並不重要。我只是想盡快完成任務。我試試 – BuildingJarl 2013-05-07 10:49:29