user4423819
user4423819

Reputation: 55

How to pass a Combobox value to BackgroundWorker without freezing the GUI C# Winform

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

Answers (1)

bokibeg
bokibeg

Reputation: 2142

There are two rules you must know:

  1. All UI elements such as text boxes and drop downs are created in the main thread and should therefore almost always be accessed from the main thread.
  2. Remember rule 1. really well. Anything you created in thread B should be used in thread B only.

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:

  • Execute the GUI logic in the main thread (also called GUI thread).
  • Execute all the background loading code from another thread.

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

Related Questions