We are using continous backgroundworker and have problem stopping them correcty. We tried different versions:
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
evCompl = new AutoResetEvent( false );
private void bw_DoWork(object sender, DoWorkEventArgs e) {
while(!bw.CancellationPending ) {
// sleep or do time wasting stuff
bw.ReportProgress( 0, /*some Data*/ );
}
if( bw.CancellationPending ) {
e.Cancel = true;
}
evCompl.Set();
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) {
Data d = (Data)e.Data;
// sometimes do some Gui stuff with invoking
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
// ...
}
protected virtual void Disposing( bool disposing )
{
if( bw!=null ) {
bw.CancelAsync();
evCompl.WaitOne();
bw.DoWork -= new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged -= new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.Dispose();
}
}
Well, this variant sometimes end in a deadlock at
evCompl.WaitOne();
and also the the bw_RunWorkerCompleted is never called. Using timed wait, e.g. evCompl.WaitOne(2000)( what is a much higher value than a loop cycle can ever need) results in titme to time null pointer exceptions.
Another not really null pointer exception free variant was:
void Dispose( bool disposing )
{
if( bw.IsBusy ) {
bw.CancelAsync();
}
bw.DoWork -= new DoWorkEventHandler(bw_DoWork );
bw.RunWorkerCompleted -= new RunWorkerCompletedEventHandler( bw_completed );
bw.ProgressChanged -= new ProgressChangedEventHandler( bw_ProgressChanged );
// ...
if( disposing ) {
bw.Dispose();
bw = null;
}
}
But I thing the reason could be "bw=null" -> inside DoWork bw is used -> null pointer acces if bw was set to null before.
In the end I need a solid way to stop the bw in Dispose and ensure that it has stopped. We put a lot of checks for bw.CancellationPending to break the while loop as soon as possible. But every way I have tried had have some side effects.
And yes: I also read a lot of threads regarding that topic...