Reputation: 5344
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
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
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
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