Reputation: 55
I am trying to pass a combobox value to BackgroundWorker in C# Winform. I am using two ways of coding, the first one below:
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
}
else
{
this.Invoke(new System.Action(() =>
{
Text = comboBox2.Text;
Text = comboBox3.Text;
}));
if (checkBox1.Checked == true) { ChkDatatoList(); }
else { UnchkDatatoList(); }
LoadDataToDGV();
ManagingDataInDGV();
}
}
The above example throws me exception, and doesn't really work.
Another way of coding is:
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
}
else
{
this.Invoke(new System.Action(() =>
{
Text = comboBox2.Text;
Text = comboBox3.Text;
if (checkBox1.Checked == true) { ChkDatatoList(); }
else { UnchkDatatoList(); }
LoadDataToDGV();
ManagingDataInDGV();
}));
}
}
Now the above code works, but it's freezing the GUI, which isn't really much useful to use the BackgroungWorker if that's the case.
So, is there a way to pass the combobox value to background worker without freezing the GUI?
Upvotes: 3
Views: 1185
Reputation: 2142
There are two rules you must know:
Since all GUI is created in the main thread, anything blocking the main thread (like your loading logic) will block the GUI, which you have witnessed yourself.
The event backgroundWorker1_DoWork
is executed on another, new thread, not the main thread. Therefore, the logic from your first code snipped breaks the first and foremost rule, you have used GUI elements outside of the main thread. You will often get cross thread operation exception because of that.
Your second code snipped does the opposite - everything is executed in the main thread, you don't want that either. What you really want is to:
With all that being said, your code would have to look something like this:
public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// TODO: Place loading logic here (i.e. load your data into a private variable)
if (this.InvokeRequired)
{
this.Invoke(new System.Action(() =>
{
// TODO: Update GUI here (i.e. bind the grid to the private variable you previously loaded
}));
}
}
And consider using the BackgroundWorker.RunWorkerCompleted event. Read up more on how the background worker works and you will have a better understanding on how to use it.
The this.Invoke
method allows you to execute code in the main thread while you are on another thread (which is the case with DoWork
event). Hope you have some better understanding now.
Upvotes: 2