2013-05-07 3 views
1

각 문자열의 길이가 약 20000 인 문자열 목록이 있습니다. 이 모든 문자열을 여러 배경 작업자를 사용하여 같은 위치에서 동일한 문자열의 반대 버전으로 바꾸려고합니다.개체에 액세스하는 C# 복수의 배경 작업자

는 Heres는 지금까지 무엇을하고 있어요 : (컴퓨터 8 개 코어를 가지고 있기 때문에 8)

배경 노동자를 설정

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

난 데 문제는 내가 무엇을 알 수 없다는 것입니다 doWork 함수를 넣는다.

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

을 또는 doWork의 기능은 반전해야하고 WorkComplete 함수에 반전 문자열을 전달 :

는 dowork 기능은 다음과 같이 루프 계속해야 하는가?

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()을 사용하여 문자열을 바꿀 수 있습니다.

그런 식으로 최적의 스레드 수를 처리합니다.

UI 스레드를 잠그지 않으려면 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); 
     } 
    } 
} 

또한, 당신은 당신이 새로운 await/async 기능을 사용하여 완전히 BackgroundWorker에 사용하지 않도록 할 수 있습니다 닷넷 4.5을 사용하는 경우.

예를 들어, 기본 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; 
    } 
} 

을, UI는 응답 유지됩니다.

+0

예를 들어 아프게 해 주셔서 감사합니다. – BuildingJarl

+0

@ 686이 작품의 작동 방식을 보려면 설명서를 약간 읽어야 할 수도 있습니다. –

+0

쿨 (cool) 좋은 해결책. 죄송합니다. 아직 충분한 담당자가 없기 때문에 투표를 할 수 없습니다. – BuildingJarl

2

BackgroundWorker를 사용하는 것이 중요합니까? 사용 TPL은 매우 간단합니다 :

using System.Threading.Tasks; 

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

TPL (기본적으로, 그것은 당신의 CPU 코어의 사용 가능한 번호를 사용합니다) 당신을위한 부하를 분산하며,이 또한 코어의 다른 양, 다른 컴퓨터에서 잘 작동합니다 .

+0

답장을 보내 주셔서 감사합니다. 배경 작업자를 사용하는 것이 중요하지 않습니다.나는 그 일이 최대한 빨리 끝나길 원한다. 아프다. 시도해 보자. – BuildingJarl