C#多个BackgroundWorkers

我正在尝试设置多个BackgroundWorker来完成工作,并且在不忙的时候开始做下一部分工作。 我似乎无法让他们正常工作。 我有以下代码。

当我将FilesToProcess设置FilesToProcess等于或小于MaxThreads它可以完美地工作,但如果我将其设置得更高,则该应用会冻结。

我确信这很简单,但我看不到它。

谢谢你的帮助 :)

松鸦

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

问题似乎是你的工人永远不会完成。 为什么会这样,我不确定; 它与你运行它们的方法(和线程)本身并没有完成这一事实有关。 我能够通过创建另一个工作人员来将文件分配给worker数组来解决问题:

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

我对这个答案不满意,因为我不知道为什么,它确实不像你最初的设计那样有效。 也许其他人可以回答......? 至少这将为您提供一个有效的版本。

编辑:您的原始版本无法正常工作,因为BackgroundWorkerFilesRunWorkerCompleted在与button1_Click (UI线程)相同的线程上运行。 由于您没有释放UI线程,因此该线程永远不会被标记为完整。