0

My codes works fine but, when I make thread I got Cross-thread operation not valid when try to add item to ComboBox. I tried this codes in backgroundworker too but same error

new Thread(GetInfo).Start();

public void GetInfo()
{
    while (true)
    {
        if (SellerControlGroup.Enabled)
        {
            SqlDataReader Type = new SqlCommand("select type from _Price where Service = 1", sqlCon.con).ExecuteReader();
            while (Type.Read())
            {
                string type = Convert.ToString(Type["type"]);
                ProgramType.Items.Add(type);
            }
            Type.Close();
        }
    }
}
Balagurunathan Marimuthu
  • 2,927
  • 4
  • 31
  • 44
C Amr Moneim
  • 41
  • 1
  • 10

2 Answers2

2

You can update the control from the thread its been created and can't update it from another thread.

Below is the working code to update the control from the same thread its been created from another thread.

new Thread(GetInfo).Start();


public void GetInfo()
{
    while (true)
    {
        if (SellerControlGroup.Enabled)
        {
            SqlDataReader Type = new SqlCommand("select type from _Price where Service = 1", sqlCon.con).ExecuteReader();
            while (Type.Read())
            {
                string type = Convert.ToString(Type["type"]);

                // Update control with the same thread its been created
                this.Invoke((MethodInvoker)delegate()
                {
                  ProgramType.Items.Add(type);
                });
            }
            Type.Close();
        }
    }
}
Aruna
  • 448
  • 3
  • 12
  • SellerControlGroup seems to a UI Control as well. – Mehrzad Chehraz Oct 15 '16 at 10:40
  • You can read the control property from another thread. Only to write, you need a delegate. – Aruna Oct 15 '16 at 10:42
  • No, it is not safe. You should not "access" a UI control from another thread. – Mehrzad Chehraz Oct 15 '16 at 10:43
  • @MehrzadChehraz Thanks, usually read is fine and won't throw any error. But if required, the above `if` can be replaced into the delegate as, `this.Invoke((MethodInvoker)delegate() { if (SellerControlGroup.Enabled){ ProgramType.Items.Add(type); } });` – Aruna Oct 15 '16 at 10:51
  • @Aruna - Read is fine so long as you don't try to write on any thread at the same time. Also this solution would be better if it did the reading in one go and then did a single invoke to update all the values. – Enigmativity Oct 15 '16 at 14:14
0

You could use a delegate to invoke the changes on the UI thread, like so

delegate void AddItemDelegate(ComboBox cmb, string value);

void AddItem(ComboBox cmb, string value) {
    if (cmb.InvokeRequired) {
        cbm.Invoke( new AddItemDelegate( AddItem ), cmb, value );
    } else {
        cmb.Items.add(value);
    }
}

and then simply use

AddItem( ProgramType, type );
Icepickle
  • 12,689
  • 3
  • 34
  • 48