I have a Windows Forms app (.NET 2.0) which launches a number of BackgroundWoker threads and handles their ProgressChanged and Completed events when they are updated/finished, respectively. However, I have come across a situation that has me guessing.
I launch BackgroundWorker 1 (BW1), followed by BackgroundWorker 2 (BW2). Let's assume BW1 finishes first and triggers the BackgroundWorkerCompleted event, which the UI thread handles in my event handler ( workerCompleted() ). The event handler takes a while because it calls out to another function.
Now I put a breakpoint at the beginning of the EventHandler and step through a run of the code. While I am stepping through the eventhandler while it is handling BW1, the UI thread suddenly switches to handling BW2.
Eventually the UI thread completes BW1 but I have a race condition that is caused by this unpredictable behavior (in that external function). Thread locking doesn't help because the UI thread ignores the lock the second time (reentrant lock).
Now, if I change the code so that right before the eventhandler calls that external function I place a Application.DoEvents(), it improves (but not totally fixes) the predictable behavior (or I should say, "my" expected behavior).
So, long winded as it may be, should the UI thread be completely finishing one eventhandler before handling the next? Or should I expect that it is non-deterministic?
void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Do some cleanup related things, generate report, etc.
...
// Call some external function to get a value which will increment on next call
int x = CallExternalFunction();
// While code is in the above function, UI switches to handling BW2 at the top of this function.
// BW2 then calls external function and finishes before BW1 returns
}
Note, there are no thread related or Application.DoEvents type code int he external function (it is actually just a queue of objects, getting one each time and incrementing an internal counter).
UPDATE: I found my answer. I'm working with code I didn't author, and oversimplified what the external function was doing. I traced and traced it until I found that eventually, it was calling Application.DoEvents which has the effect of interrupting the current eventhandler, and forcing the UI to handle other events.
My apologies for being blind and lazy. Maybe this alone will help someone who finds this later.