C# 使ComboBox数据源集加载异步

C# 使ComboBox数据源集加载异步,c#,winforms,performance,asynchronous,combobox,C#,Winforms,Performance,Asynchronous,Combobox,我想用50000个项目填充一个组合框 问题是。。。将所有项目加载到GUI中需要花费太多时间 所以我尝试填充Asynchronous: 首先,我创建数据源数组: var source = Enumerable.Range(1, 50000).Select(e => new{ID = e}).ToArray(); 然后设置组合框的datasource属性: BeginInvoke(new Action(() => comboBox1.DataSource = source));

我想用50000个项目填充一个组合框

问题是。。。将所有项目加载到GUI中需要花费太多时间

所以我尝试填充Asynchronous:

首先,我创建数据源数组:

  var source = Enumerable.Range(1, 50000).Select(e => new{ID = e}).ToArray();
然后设置组合框的datasource属性:

  BeginInvoke(new Action(() => comboBox1.DataSource = source));
上述代码行的问题需要花费大量时间才能完成,并且窗口冻结

我使用的解决方法是将数据源设置为null,并在foreach语句中添加该项,每次调用Application.DoEvents()

        comboBox1.DataSource = null;
        foreach (var e in source)
        {
            comboBox1.Items.Add(e);
            Application.DoEvents();
        }
它工作得很好,但是我需要将comboBox与数据源绑定,这样我就不能


如何设置数据源并使其像上面的代码那样加载?

带有100项的组合框是个坏主意,但如果您坚持填充5000项

获取好的老
backgroundworker
并将其连接起来以加载数据源,不管它是哪个对象,比方说一个数组。在伪代码中(这些方法可能有参数)


我不确定这对您的情况是否有帮助,但如果您正在设置DisplayMember和ValueMember,请确保始终将DataSource设置为最后一个。 这有很大的不同。
此处的详细信息:

我正试图用50000项填充组合框。
这听起来是个非常糟糕的主意,无论是从用户体验还是从用户界面性能来看。@EricJ。我知道,但是用户现在需要这种方式。实际上是5.000项,但出于测试目的,我正在使用50.000项来查看异步方式是否真正起作用您是否尝试将虚拟化设置到您的UI控件?滚动时会有点痛,但当绑定完全超出UI范围的数据时,UI不需要执行任何操作。即使是5000个项目,无论在性能还是可用性方面都很糟糕。事实上,你为了让它发挥作用而跳出了障碍,这应该表明你走错了路@cscmh99的想法是正确的。@cscmh99我使用winforms,我不知道如何使用组合框来实现这一点。有办法吗?谢谢你的回答,但是数组创建很快,问题是设置数据源。这是慢的部分…->cbo.DataSource=myArrayOfValues@乔治:那么答案是这样的。在BG线程上设置数据源,表单将保持响应。或者你说上面的代码冻结了表单?是的,因为cbo.DataSource=myArrayOfValues在主线程中运行,即使我输入dowork,它也会抛出交叉线程异常。而cbo.Invoke不能解决这个问题,因为设置发生在主线程中,而没有调用application.doeventsinternaly@George然后,有一些东西将不会冻结你的形式。检查更新。这将没有数据源,但它将添加您的项目而不冻结。是的,您不想在
doWork
上设置combo,因为该方法运行在不同的线程上。这就是为什么您有
已完成的工作
进度
。因此,您可能必须放弃datasource属性以加载async而不是冻结HI T.S,但这正是我不想要的,我需要绑定组合。。。在我的问题中,我已经用application.doevents做了foreach add。。。这不会冻结我的窗口…但我确实需要数据源:(
void DoWork() // handles loading of an array
{ 
    // load array here. cbo is disabled 
    myArrayOfValues = <whatever you get from DB>
    foreach var item in myArrayOfValues 
    {

        // here call `worker.Progress` and pass your item in argument
    }
}

void OnWorkComleted(....) 
{ 
   // Set your combo as disabled initially, so people can't click while it is loading


    cbo.Enabled = true;

}

void OnWorkerProgress(....) 
{ 
    // Add items one by one
    cbo.Items.Add(myValue);

}
class Itm
{
    string A {get; set;}
    string B {get; set;}
    string C {get; set;}
}


void Setup()
{
    for (int i = 1; i < 4; i++)
    {
        cbo.Items.Add(new itm { a = "A" + i, b = "B" + i, c = "C" + i});
    }
    cbo.DisplayMember = "A";
    cbo.ValueMember = "B";
}


void OnSelectedIndexChanged(....)
{
     if (cbo.SelectedIndex > -1)
     {
         var item = (itm)cbo.SelectedItem;
         MessageBox.Show(string.Format("Selected: {0}, {1}, {2}", item.A, item.B, item.C));
     }
}