Prev: Using WaitCursor or ProgressBar
Next: w3wp进程死掉
From: thezim on 11 Dec 2007 21:51 I'm trying to figure out why the following doesn't work. It hang waiting for a BackGroundWorker to become "un busy". With the 11 item in the queue the first 10 get to the DoWork but never to RunCompleted. If the items in the queue are equal to MaxWorker then everything works okay. I am goin insane. I knows its some hidden inherent way im doing something that i have yet to see documented or maybe im just in over my head. using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; using System.Diagnostics; namespace WindowsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private BackgroundWorker[] Workers; private int MaxWorkers = 10; private void button1_Click(object sender, EventArgs e) { Queue<string> Clients = new Queue<string>(); Clients.Enqueue("TEST01"); Clients.Enqueue("TEST02"); Clients.Enqueue("TEST03"); Clients.Enqueue("TEST04"); Clients.Enqueue("TEST05"); Clients.Enqueue("TEST06"); Clients.Enqueue("TEST07"); Clients.Enqueue("TEST08"); Clients.Enqueue("TEST09"); Clients.Enqueue("TEST10"); Clients.Enqueue("TEST11"); Workers = new BackgroundWorker[MaxWorkers]; for (int i = 0; i < MaxWorkers; i++) { Workers[i] = new BackgroundWorker(); Workers[i].WorkerSupportsCancellation = true; Workers[i].DoWork += new DoWorkEventHandler(bw_DoWork); Workers[i].RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); } while (Clients.Count != 0) { for (int i = 0; i < 10; i++) { if (!Workers[i].IsBusy) { string hostname = Clients.Dequeue(); Debug.WriteLine("Starting " + hostname); Workers[i].RunWorkerAsync(hostname); } } } } private void bw_DoWork(object sender, DoWorkEventArgs e) { Debug.WriteLine("Working " + e.Argument.ToString()); e.Result = e.Argument.ToString(); } private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Debug.WriteLine("Completed " + e.Result); } } }
From: Peter Duniho on 11 Dec 2007 23:46 On Tue, 11 Dec 2007 18:51:15 -0800, thezim <thezim(a)gmail.com> wrote: > I'm trying to figure out why the following doesn't work. It hang > waiting for a BackGroundWorker to become "un busy". With the 11 item > in the queue the first 10 get to the DoWork but never to RunCompleted. > If the items in the queue are equal to MaxWorker then everything works > okay. > > I am goin insane. I knows its some hidden inherent way im doing > something that i have yet to see documented or maybe im just in over > my head. The main problem is that one of the main points of using the BackgroundWorker class is that the RunWorkerCompleted event is raised on the same thread that created the BackgroundWorker instance, but you have blocked the raising of any events on your main thread by never returning from the Click event handler. The fact that you're polling the BackgroundWorker list is bad, and you have a potential crashing bug waiting to happen because you don't check for an empty queue before trying to dequeue a new item for working. But the main problem is that you are stuck in your Click handler, preventing the RunWorkerCompleted events from being raised. The fix would be to move the code that enqueues new work items from the click handler to the RunWorkerCompleted event. Actually, that's a fix for at least two problems: the one where your code doesn't return from the Click handler, as well as the problem where your code is polling the list of BackgroundWorkers. I've posted a fixed version of your program below. The technique of using the sender to start a new background task in the RunWorkerCompleted event also serendipitously fixes the problem that each time the button is clicked a new array of BackgroundWorkers is created (but there remains the problem that you never dispose the BackgroundWorker instances...hopefully both problems are more related to the demonstration nature of the code, rather than something you'd include in a real program :) ). Hope that helps. Pete using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Threading; namespace TestQueueBGWorker { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private BackgroundWorker[] Workers; private int MaxWorkers = 10; private Queue<string> Clients = new Queue<string>(); private void button1_Click(object sender, EventArgs e) { Clients.Enqueue("TEST01"); Clients.Enqueue("TEST02"); Clients.Enqueue("TEST03"); Clients.Enqueue("TEST04"); Clients.Enqueue("TEST05"); Clients.Enqueue("TEST06"); Clients.Enqueue("TEST07"); Clients.Enqueue("TEST08"); Clients.Enqueue("TEST09"); Clients.Enqueue("TEST10"); Clients.Enqueue("TEST11"); Workers = new BackgroundWorker[MaxWorkers]; for (int i = 0; i < MaxWorkers; i++) { Workers[i] = new BackgroundWorker(); Workers[i].WorkerSupportsCancellation = true; Workers[i].DoWork += new DoWorkEventHandler(bw_DoWork); Workers[i].RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); _StartNewClient(Workers[i]); } Debug.WriteLine("Finished Click handler"); } private void _StartNewClient(BackgroundWorker bw) { if (Clients.Count > 0) { string hostname = Clients.Dequeue(); Debug.WriteLine("Starting " + hostname); bw.RunWorkerAsync(hostname); } } private void bw_DoWork(object sender, DoWorkEventArgs e) { Debug.WriteLine("Working " + e.Argument.ToString()); Thread.Sleep(1000); e.Result = e.Argument.ToString(); } private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Debug.WriteLine("Completed " + e.Result); _StartNewClient((BackgroundWorker)sender); } } }
From: Peter Duniho on 11 Dec 2007 23:55 On Tue, 11 Dec 2007 20:46:36 -0800, Peter Duniho <NpOeStPeAdM(a)nnowslpianmk.com> wrote: > [...] > I've posted a fixed version of your program below. And just in case it wasn't clear: the call to Thread.Sleep() is definitely not necessary, and you wouldn't put it into a working application. I added it as part of testing the new version, and just didn't bother removing it before posting the new sample. Pete
|
Pages: 1 Prev: Using WaitCursor or ProgressBar Next: w3wp进程死掉 |