Search code examples
c#winformsbackgroundworker

BackgroundWorker reporting ProgressChanged after closing its form


In my winforms project I got some Form, that runs BackgroundWorker. Basically it's a simulation, so it can be solved at some point but it can also be stopped by the user, so when it finishes either way it needs to redraw the results. I got a problem with the fact, that when I close main window its reference becames null, but BW can still fire ReportProgress, which ends up with an exception.

My BackgroundWorker (simplified code):

void backgroundWorkerRunSimulation_DoWork(object sender, DoWorkEventArgs e)
{
    bool ShouldContinue = true;
    do
    {
        SomeHeavyComputing();
        if(CheckIfSimulationDone() | backgroundWorkerRunSimulation.CancellationPending)
            ShouldContinue=false;

        //Redrawing results on the interface
        if (AlwaysRefresh | !ShouldContinue)
            UpdateGUI();    //<--Method invoked on form's thread

        //Reporting progress
        backgroundWorkerRunSimulation.ReportProgress(0, SomeReportingObject);
    }
    while(ShouldContinue);
}

And ReportProgress:

    private void backgroundWorkerRunSimulation_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        UpdateStatusBar((GUIReportInfo)e.UserState);//<-also invoked on form's thread

    }

Where

void UpdateStatusBar(GUIReportInfo ReportInfo)
{
    if (this.InvokeRequired)
    {
        ReportInfoDelegate updateStatusBar = new ReportInfoDelegate(UpdateStatusBar);
        this.Invoke(updateStatusBar, new object[] { ReportInfo });
    }
    else
        //Some assignments on form - crashes here, null reference exc
}

Obviously UpdateStatusBar shouldn't be fired up, and I'm suprised that UpdateGUI (which is analogic) doesn't crash. But is there any way to check whether the form is still there? Adding:

this.Invoke(new MethodInvoker(delegate { this.Close(); }));

to FormClosing event seems to solve the problem, though I don't understand why would that work. Isn't Close() method fired up on the form's thread anyway?

I'd be glad for any help.


Solution

  • I'm guessing that the added invoke just accidentally changes the order of events, so it won't crash. The elegant solution would be to implement FormClosing and abort the BW there, and wait for it till it finishes. Also, in the BW code you should check for "CancellationPending". More information here:

    http://msdn.microsoft.com/en-us/library/hybbz6ke.aspx

    EDIT: The top-voted answer from here demonstrates the solution: How to stop BackgroundWorker on Form's Closing event?