invoke during background worker

15,353

Solution 1

I'm not quite sure how you want to use the values, but just to give you an example, you could easily just do this in the BackgroundWorker thread:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    string input_ip_r = "";
    this.Invoke(new Action(() => 
    {
        // Don't know what "lc" is (a loop variable?)
        input_ip_r = listView1.Items[lc].SubItems[1].Text;
    }));
}

See this answer for other ways of doing the same (this is for >= .Net 3.5)

Solution 2

1) Don't put RunWorkerAsync as the method to invoke. It's not actually running the method that you think. What you should really put there is something like this:

this.Invoke(new MethodInvoker(MethodToUpdateUI));

MethodToUpdateUI should be some new method that you create that specifically does whatever UI updates should be made in this context.

2) There's no need for InvokeRequired. You're in a background thread. Invoking will always be required.

To be honest, the entire patter of if(invoke required) call myself else do stuff is an odd construct which I dislike. InvokeRequired should pretty rarely be used. You should almost always know whether you're in the UI thread or a background thread, if you don't, chances are something wrong (either you're always in one or the other and you just don't know which, or it shouldn't be non-deterministic). Usually this means having methods that must be run in the UI thread. If you're already in the UI thread you just call them, if you're in a background thread and know it then you call Invoke first.

On top of that, Invoke works just fine even if you call it when you're already in the UI thread, so there's really no significant negative consequences to just calling Invoke regardless of whether you're in a background thread or already in the UI thread.

3) Usually it's best to separate code for solving business problems from UI code. It's code smell to be invoking from within DoWork's handler. If this is right near the end, you should probably be adding an event handler to RunWorkerCompleted. If you're calling this periodically to update the UI with progress of the worker, you should be using ReportProgress and handling the ProgressReported event. For getting info from the UI for use in a long running task you should access it before starting the background task. For exceptional cases that aren't any of those, it may be appropriate to use Invoke, but the remaining cases ought to be rare.

Share:
15,353
Dasher Labs
Author by

Dasher Labs

Updated on June 04, 2022

Comments

  • Dasher Labs
    Dasher Labs almost 2 years

    I need to invoke this: string input_ip_r = listView1.Items[lc].SubItems[1].Text; so I used

    if (InvokeRequired)
    {
        this.Invoke(new MethodInvoker(function));
        return;
    }
    

    This worked but now I have put it into a BackgroundWorker and using this

    if (InvokeRequired)
    {
        this.Invoke(new MethodInvoker(bw.RunWorkerAsync));
        return;
    }
    

    it gives an error that you can only run BackgroundWorker one at a time.

    So how do I invoke while in the Backgroundworker?

  • Dasher Labs
    Dasher Labs over 11 years
    I need to set this value listView1.Items[lc].SubItems[1].Text inside the background worker without cross thread calls
  • Servy
    Servy over 11 years
    @user1335937 Okay. That's what my answer is helping you address.
  • Dasher Labs
    Dasher Labs over 11 years
    I'm quite new to c#, so I have a loop to get each listview item from subitem 2 and how to do get it inside the background worker to use?
  • Servy
    Servy over 11 years
    @user1335937 Take all of the items out of the listview and put them into a data structure, such as a List or array. Then store that as a private instance field and use it in the background worker. That way you're not accessing the UI from the background worker in the first place.
  • Mario S
    Mario S over 11 years
    I'm glad it worked for you =) Remember though, that this is just one of the ways you can go with it. @Servy answer has points that also should be considered.