fdh
fdh

Reputation: 5344

Using BackgroundWorker in C#?

I have two questions about using a BackgroundWorker:

1)Lets say you have Function A and Function B. Function A creates a BackgroundWorker which runs Function B. So the BackgroundWorker is now running Function B on a separate thread. Function B is an infinite while loop that I intend to run for a long duration. After Function A uses the BackgroundWorker through, it returns. So now that the function that initiated the BackgroundWorker (Function A) has returned, does the BackgroundWorker thread keep running in the background? Or does it stop running Function B since the function that instantiated it has returned? If it does stop, how would I make it so that Function B continues to run even after Function A has returned?

2)I need to access Window Forms Items (i.e. Textbox) from a separate thread created by a BackgroundWorker. However if I try to access Window Forms Items from a thread that is not main, I get a cross threading error. How could I safely access Window Forms Items from a separate thread? I basically need to keep updating a textbox from a separate thread. I know a BackgroundWorker has a member called "RunWorkerCompleted" and that is run after the BackgroundWorker completes its job. It allows me to access Window Forms Items from this. However, I need to access a Window Forms Item during the duration of my thread rather than after its completion. How could I access these safely through a thread? If this isn't possible what are some other possible solutions to the problem?

Upvotes: 2

Views: 489

Answers (3)

Manjunath K Mayya
Manjunath K Mayya

Reputation: 1118

For the second question:

Even i faced the same problem once. So used the _DoWork method.
This is how it worked for me

 private void bgwLongTask_DoWork(object sender, DoWorkEventArgs e)
 {

    my long task
    {
      //in between the long task, i want to udpate the datagrid view dataGridView1

      if (dataGridView1.InvokeRequired)
         dataGridView1.Invoke(myGridBindDelegate);
      else
         BindDataToGrid();
     }
 }

Here myGridBindDelegate is the delegate which calls the datagrid view binding method.

    delegate void GridBindDelegate();
    GridBindDelegate myGridBindDelegate;
    myGridBindDelegate = BindDataToGrid;

    private void BindDataToGrid()
    {
        dataGridView1.DataSource = dt; //dt is a datatable which is public
        dataGridView1.Refresh();
    }

Worked for me.

Upvotes: 1

Amar Palsapure
Amar Palsapure

Reputation: 9680

The answer by Jim is correct.

In part two, you said

I need to access Window Forms Items (i.e. Textbox) from a separate thread created by a BackgroundWorker.

So now if you want to do this way only then you will need to do is create an extension method like below

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null);
        else action.Invoke();
    }
}

Now when you are accessing the text box from your Non-UI thread, you will need to do it like this

txtBox.Invoke(() => { txtBox.Text = "Text Changed from Non-UI thread"; });

Hope this helps you.

Upvotes: 1

Jim Mischel
Jim Mischel

Reputation: 133995

1) The BackgroundWorker will continue to run after Function A returns.

2) Create a ProgressChanged event handler that updates the text box, and have the BackgroundWorker call ReportProgress whenever you want to change the text. Of course, you'll have to make the BackgroundWorker set a property that the ProgressChanged event can read. This works because the ProgressChanged event handler is called on the UI thread.

Upvotes: 4

Related Questions