2012-05-22 8 views
7

BackgroundWorkerは複数の作業を行うように設定しようとしていますが、ビジーでない場合は次の作業を開始します。私は彼らが正しく働くように思えない。私は以下のコードを持っています。C#複数のBackgroundWorkers

FilesToProcessMaxThreads以下に設定すると、それを高くするとアプリがフリーズしますが、完全に機能します。

私はそれが何か簡単だと確信していますが、私はそれを見ることができません。任意の助け

感謝:)

ジェイ

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'について質問していますが、TPLやRxを使わないのはなぜですか?彼らはこれをずっと簡単にするでしょう。 – Enigmativity

+3

UIスレッドでスリープ状態でデッドロックを作成しています。 RunWorkerCompletedイベントハンドラが実行されないようにする。 –

答えて

7

問題は、あなたの労働者が完成されることはありませんということであるように思われます。なぜこれが、私は分からない。それはあなたがそれらから実行しているメソッド(およびスレッド)がそれ自身完了していないという事実とは関係があります。まさに、それはように動作しませんでした、なぜ私は知らないので、私はこの答えに満足していないよ

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

:私は、労働者の列にファイルを割り当てるには、別の作業員を作成することで問題を解決することができましたあなたはもともとそれを設計しました。多分誰かがそれに答えることができます...?少なくともこれはあなたに働くバージョンを手に入れるでしょう。

編集:BackgroundWorkerFilesRunWorkerCompletedbutton1_Click(UIスレッド)と同じスレッドで動作するため、元のバージョンが機能しませんでした。あなたはUIスレッドを解放していないので、スレッドは完全なものとしてマークされることはありません。