2012-05-22 12 views
7

मैं काम करने के लिए कई BackgroundWorker एस सेट करने की कोशिश कर रहा हूं और व्यस्त होने पर व्यस्त नहीं होने पर व्यस्त हूं। मैं उन्हें ठीक से काम नहीं कर पा रहा हूं। मेरे पास नीचे कोड है।सी # एकाधिक पृष्ठभूमिवर्कर्स

जब मैं 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 या आरएक्स का उपयोग नहीं? वे इसे इतना आसान बना देंगे। – Enigmativity

+3

आप यूआई थ्रेड पर सोने से डेडलॉक बना रहे हैं। RunWorker पूर्ण ईवेंट हैंडलर को चलने से रोकना। –

उत्तर

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 थ्रेड) के समान थ्रेड पर चलता है। चूंकि आप यूआई थ्रेड को मुक्त नहीं कर रहे हैं, इसलिए थ्रेड को पूर्ण रूप से चिह्नित नहीं किया जा रहा है।