views:

179

answers:

2

I've got a background worker on a form and I've written some long running DB interaction in it.

When I click a button on my form, the following runs:

if (!bwFind.IsBusy)
    bwFind.RunWorkerAsync(param);

Where bwFind is the BackgroundWorker and param is a DevExpress CriteriaOperator.

I update a progressbar in the Progress_Changed event handler.

And I do the following in the RunWorkerCompleted event handler:

dataGrid.DataSource = this.dataObject;
dataGrid.Refresh();
label1.Text = this.dataObject.Count.ToString(); // problem appears here

Problem is, that I get a Null Ref Exception at the line noted, however I instantiate that object, at the end of the DoWork method.

I know that DoWork isn't running, cause if I do a null-check before using it, press the button on the form a second time... it runs, and all works as expected.

Maybe I'm not using the BackgroundWorker correctly, but this happens very often whenever I use the component.

+2  A: 

There is a specific pattern for implementing RunWorkerCompleted.

  • First, Check e.Error (Exceptions)
  • Second, Check for Cancelation, if supported
  • And finally, Accept result

And you normally assign the result to e.Result in DoWork to transfer it to RunWorkerCompleted, but you use a class member for that. Make sure the use of this.dataObject is thread-safe.

   void backgroundWorker1_RunWorkerCompleted(object sender, 
        RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown.
        if (e.Error != null)
        {
            label1.Text = e.Error.Message;
        }
        else if (e.Cancelled)
        {
            label1.Text = "Canceled";
        }
        else
        {
            // Finally, handle the case where the operation 
            // succeeded.
            label1.Text = this.dataObject.Count.ToString();
        }

        // update UI for Thread completed
    }
Henk Holterman
Turns out I was modifying a UI item in DoWork. Checking e.Error.Message indicated this. Thank you. I thought the whole point of using the BackgroundWorker was so that I didn't have to (Begin)Invoke?
SnOrfus
You still have to Invoke from DoWork. (Only) the Completed and Progress events are Invoked to the main thread.
Henk Holterman
A: 

There is one more issue. You'll not get you Complete if the parent thread was killed/aborted.

Vasiliy Borovyak
He was getting ther null ref exception in the parent thread (== mainthread).
Henk Holterman
Oops... Yeah, stupid me.
Vasiliy Borovyak