3

Below is my coding:

    Form2 msgForm;
    private void button3_Click_1(object sender, EventArgs e)
    {

        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        //bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

        msgForm = new Form2();

        try
        {
            bw.RunWorkerAsync();

            msgForm.ShowDialog();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        if (comboBox15.Text == "")
        {
            //MessageBox.Show("Please select Printer ID.", "Status", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //return;
        }
        // Coding that transmit protocol and will last around 2 minutes.
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        msgForm.Close();
    }

When I run this background worker coding, there's an error stating "Cross-thread operation not valid: Control 'comboBox15' accessed from a thread other than the thread it was created on."

How do I solve this problem guys?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Coolguy
  • 2,225
  • 12
  • 54
  • 81
  • 1
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Sep 20 '12 at 10:08

5 Answers5

5

You can use Invoke:

// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.comboBox15.InvokeRequired)
{
    this.Invoke((MethodInvoker) delegate {if (comboBox15.Text == ""){// What you want to do}});
}
else
{
    if (comboBox15.Text == "")
    {
    }
}

also read the following:
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx
Anonymous method in Invoke call

Community
  • 1
  • 1
Dor Cohen
  • 16,769
  • 23
  • 93
  • 161
1

You can't UI elements from a non-UI-thread. Ideally, provide the relevant information to the background worker before it starts, e.g.

string text = combo15.Text;
bw.DoWork += (sender, args) => TransmitStuff(combo15.Text, args);

...

void TransmitStuff(string printerId, DoWorkEventArgs e)
{
    ...
}

If you can use .NET 4.5 and C# 5, you could use an async method to quite possibly make all of this easier... but I realize that's unlikely to be an option for you.

EDIT: While you can use Invoke, that ends up being quite messy - and you've got potentially inconsistent state. I generally think it's tidier to work out all the state you need before you start the long-running operation, validate it all, and then hand it to the operation. If you need to update the UI during the operation, you can use the BackgroundWorker progress facilities.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

In BackgroundWorker, when we call any user controls its problem. Please use this property in Window Form Load event:

 CheckForIllegalCrossThreadCalls = false;
Surya
  • 15,703
  • 3
  • 51
  • 74
0

You can only access gui controls from your main thread.

Move the

if (comboBox15.Text == "")

part to button3_click

Thomsen
  • 773
  • 7
  • 14
0

You can get round it by passing the value such as below.

private void Dowork()
{
    backgroundWorker1.RunWorkerAsync(comboBox1.Text);
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    String selected = (String)e.Argument;
    if (String.IsNullOrEmpty(selected)) return;
    //do stuff
}
BugFinder
  • 17,474
  • 4
  • 36
  • 51
  • BudFinder, I'm using your answer and can run perfectly. But my form will freeze when the backgroundworker is running. How to solve it? – Coolguy Sep 20 '12 at 08:05
  • Mine didnt.. Failing that, set a string to the value of the combo box, pass that, and remember all code in your "dowork" routine must reference the passed string, not the combo box... – BugFinder Sep 20 '12 at 08:08