2012-05-22 11 views
7

Çalışmak için birden çok BackgroundWorker s kurmaya çalışıyorum ve meşgul olmadığında işin bir sonraki işini yapmaya başla. Onları düzgün şekilde çalıştırıyor gibi görünmüyorum. Aşağıdaki kodum var.C# Çoklu BackgroundWorkers

FilesToProcess değerini eşit veya MaxThreads'dan daha düşük bir değere ayarladığımda, daha yüksek bir performans göstersem de uygulama mükemmel bir şekilde çalışır.

Bunun basit bir şey olduğundan eminim, ama göremiyorum. Herhangi bir yardım için

Teşekkür :)

Jay sorun işçiler asla tamamladıktan olduğunu görünmektedir

using System; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows.Forms; 

namespace bgwtest 
{ 
    public partial class Form1 : Form 
    { 
     private const int MaxThreads = 20; 
     private const int FilesToProcess = 21; 
     private BackgroundWorker[] threadArray = new BackgroundWorker[MaxThreads]; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1Load(object sender, EventArgs e) 
     { 
      InitializeBackgoundWorkers(); 
     } 

     private void InitializeBackgoundWorkers() 
     { 
      for (var f = 0; f < MaxThreads; f++) 
      { 
       threadArray[f] = new BackgroundWorker(); 
       threadArray[f].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork); 
       threadArray[f].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted); 
       threadArray[f].WorkerReportsProgress = true; 
       threadArray[f].WorkerSupportsCancellation = true; 
      } 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      for (var f = 0; f < FilesToProcess; f++) 
      { 
       var fileProcessed = false; 
       while (!fileProcessed) 
       { 
        for (var threadNum = 0; threadNum < MaxThreads; threadNum++) 
        { 
         if (!threadArray[threadNum].IsBusy) 
         { 
          Console.WriteLine("Starting Thread: {0}", threadNum); 

          threadArray[threadNum].RunWorkerAsync(f); 
          fileProcessed = true; 
          break; 
         } 
        } 
        if (!fileProcessed) 
        { 
         Thread.Sleep(50); 
        } 
       } 
      } 
     } 

     private void BackgroundWorkerFilesDoWork(object sender, DoWorkEventArgs e) 
     { 
      ProcessFile((int)e.Argument); 

      e.Result = (int)e.Argument; 
     } 

     private static void ProcessFile(int file) 
     { 
      Console.WriteLine("Processing File: {0}", file); 
     } 

     private void BackgroundWorkerFilesRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Error != null) 
      { 
       MessageBox.Show(e.Error.Message); 
      } 

      Console.WriteLine("Processed File: {0}", (int)e.Result); 
     } 
    } 
} 
+1

"BackgroundWorker" hakkında soru sorduğunuzu biliyorum, ancak neden TPL veya Rx kullanmıyorsunuz? Bunu çok daha basit yaparlardı. – Enigmativity

+3

UI iş parçacığında uyuyarak kilitlenme oluşturuyorsunuz. RunWorkerCompleted olay işleyicilerinin çalışmasını engeller. –

cevap

7

. Neden bu, emin değilim; Onları çalıştırdığınız yöntemin (ve iş parçacığının) kendisini tamamlamaması gerçeğiyle bir ilgisi vardır. Tam olarak o kadar işe yaramadı, neden bilmiyorum çünkü bu cevap memnun değilim

private BackgroundWorker assignmentWorker; 

    private void InitializeBackgoundWorkers() { 
     assignmentWorker = new BackgroundWorker(); 
     assignmentWorker.DoWork += AssignmentWorkerOnDoWork; 
     // ... 
    } 

    private void AssignmentWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs) { 
     for(var f = 0; f < FilesToProcess; f++) { 
      var fileProcessed = false; 
      while(!fileProcessed) { 
       for(var threadNum = 0; threadNum < MaxThreads; threadNum++) { 
        if(!threadArray[threadNum].IsBusy) { 
         Console.WriteLine("Starting Thread: {0}", threadNum); 

         threadArray[threadNum].RunWorkerAsync(f); 
         fileProcessed = true; 
         break; 
        } 
       } 
       if(!fileProcessed) { 
        Thread.Sleep(50); 
        break; 
       } 
      } 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     assignmentWorker.RunWorkerAsync(); 
    } 

: Ben işçi dizisine dosyaları atamak için başka işçiyi oluşturarak sorunu çözmek başardı Orijinal olarak tasarladınız. Belki de başka biri buna cevap verebilir ...? En azından bu size bir çalışma sürümü kazandıracak.

DÜZENLEME: Orijinal sürümünüz çalışmadı çünkü BackgroundWorkerFilesRunWorkerCompleted, button1_Click (UI iş parçacığı) ile aynı iş parçacığı üzerinde çalışır. UI iş parçacığını serbest bırakmadığınız için iş parçacığı hiçbir zaman tam olarak işaretlenmez.