简体   繁体   中英

Setting ComboBox DataSource from backgroundWorker in C#

I have a problem with populating my comboBoxes in a WinForm application that I'm writing. The data that I use to populate these comboBoxes is pulled from database. The problem is that there is a lot of data that needs to be binded to the comboBoxes, so this process takes a very long time during which the entire application is locked (the entire process of binding data takes over 9 seconds, while the process of pulling the data from the database takes only 400 milliseconds). I'm trying to speed things up by splitting the processes of creating the controls (main thread) and populating the comboBoxes (background worker), but naturally I get the cross thread error. This is the part of code that I use:

private void Populate()
    {                                  
        comboBox1.BindingContext = new System.Windows.Forms.BindingContext();
        comboBox1.DataSource = MyClass.dtMyDataTable;
        comboBox1.DisplayMember = "TitleColumn";

        .//I repeat the same code for each comboBox
        .//I use the BiningContext because some of the comboBoxes have to display the 
        .//same data.            
    }

I created a class that contains all DataTables that I need in this form - there are multiple forms that use the same data from the database, so I created a class and created an object that fills all of these DataTables on the parent Form.Load(), and then I pass them to the children forms when I create them. This way I load the data when the application loads (it doesen't even take that long), so it should be ready to use when I call it from child forms. I've tried to call the Populate() method from backgroundWorker.DoWork() method, and there I get the cross thread error.

My question is - is there a way to make this work, and if not, what could I use as alternative solution.

Thank you

I'm not a full bottle on invoking but try this:

PopulateData()
{
    if (combobox1.InvokeRequired)
    {
        combobox1.Invoke(new EventHandler(delegate(object o, EventArgs a)
            {
                PopulateData();
            }
                ));
    }
    else
    {
        // Do your updates here...
    }
}

I believe this will find the thread responsible for combobox1, which is going to be the same thread for the other combo's, and then run.

I'm sure someone else will chime in with a better way to invoke perhaps at the form level ?

I've found a good alternative, and it sped things up from 9 seconds to 1.5 seconds. The solution is to place the comboBox.DisplayMember BEFORE the 'comboBox.DataSource' line because when you change the DisplayMember (or ValueMember) the data source repopulates itself. So if the comboBox.DisplayMember is after the 'comboBox.DataSource' line, the data source populates itself 2 times (I think that ClearBeforeFill is enabled by default when binding data sources, that is why there are no duplicates in the binded data).

Thanks anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM