WinForn程序,窗口加载时,向窗体中的三个ComboBox控件绑定数据源,并设置DisplayMember和ValueMember属性.
数据源大于10万条记录.打开窗体Very慢.等待时间大于7秒.最要命的是窗口卡住.必需加载完成才可用..遂采用多线程..
以下为代码片断.. public delegate void SetValueDisplayDelegate();        public void StartSet()
        {
            //为三个ComboBox绑定数据源..方法已经封装.此处调用.
            SaleBind.BindSaleProduct(cbBoxProductID, cbBoxProductName, cbBoxBarCode);
            //创建线程1
            Thread productIDThread = new Thread(new ThreadStart(DoneProductID));
            productIDThread.Name = "ProductID";
            productIDThread.SetApartmentState(ApartmentState.STA);
            productIDThread.Start();
            //创建线程2
            Thread productNameThread = new Thread(new ThreadStart(DoneProductName));
            productNameThread.Name = "ProductName";
            productNameThread.SetApartmentState(ApartmentState.STA);
            productNameThread.Start();
            //创建线程3
            Thread barCodeThread  = new Thread(new ThreadStart(DoneBarCode));
            barCodeThread.Name = "BarCode";
            barCodeThread.SetApartmentState(ApartmentState.STA);
            barCodeThread.Start();
        }
        private void DoneProductID()
        {
            cbBoxProductID.Invoke(new SetValueDisplayDelegate(SetProductIDMapping));
        }        private void DoneProductName()
        {
           cbBoxProductName.Invoke(new SetValueDisplayDelegate(SetProductNameMapping));
        }        private void DoneBarCode()
        {            cbBoxBarCode.Invoke(new SetValueDisplayDelegate(SetBarCodeMapping));
        }        //经查证,绑定数据源只需1秒,慢的原因在于指定DisplayMember 和ValueMember .
        private void SetProductIDMapping()
        {
            cbBoxProductID.DisplayMember = "ProductID";
            cbBoxProductID.ValueMember = "ProductID";
            cbBoxProductID.AutoCompleteSource = AutoCompleteSource.ListItems;
            cbBoxProductID.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        }        private void SetProductNameMapping()
        {
            cbBoxProductName.DisplayMember = "ProductName";
            cbBoxProductName.ValueMember = "ProductID";
            cbBoxProductName.AutoCompleteSource = AutoCompleteSource.ListItems;
            cbBoxProductName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        }        private void SetBarCodeMapping()
        {
            cbBoxBarCode.DisplayMember = "BarCode";
            cbBoxBarCode.ValueMember = "ProductID";
            cbBoxBarCode.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            cbBoxBarCode.AutoCompleteSource = AutoCompleteSource.ListItems;
        }
        //启用了一个后台进程.
        private void backgroundWorkerMain_DoWork(object sender, DoWorkEventArgs e)
        {
            StartSet();
        }
        
        //窗口加载事件
        private void FormSale_Load(object sender, EventArgs e)
        {
            backgroundWorkerMain.RunWorkerAsync();
        }
    }经查证,绑定数据源只需1秒,慢的原因在于指定DisplayMember 和ValueMember .为什么?
另外,调试发现,3个线程都停在了各自的创建委托代码块..事实是,是主线程在执行全部代码..昏中...
求优化解决方案..

解决方案 »

  1.   

    用 combobox的  BeginInvoke试下
      

  2.   

    你这样开线程和没开区别不是很大..
    在线程里 循环一行一行的添加.在循环里使用Application.DoEvents(); 看看.
      

  3.   


    我觉得应该是在主线程中(也就是循环外)使用 Application.DoEvents() :        //启用了一个后台进程.(这应该是后台线程吧?)
            private void backgroundWorkerMain_DoWork(object sender, DoWorkEventArgs e)
            {
                StartSet();            while (后台线程.IsAlive)
                {
                    Application.DoEvents();
                }        }
            
      

  4.   

    我也刚接触多线程,在这想提一下我的见解希望对楼主有所帮助
    invoke和begininvoke的调用,实际上也是让UI线程来做的,所以在工作线程上直接使用invoke意思就不大了,
    应该如下
    // workThread
    TODO: 耗时的操作
    TODO: invoke以上嵌套在循环也行,只在invoke不要调用得太频繁,UI界面就不太死住了顺便
      

  5.   

    在循环里使用Application.DoEvents()
      

  6.   

    数据也太大了,现实中不会遇到这样的问题,这样没有任何用户体验可言。就问题而言,如果没有设置DisplayMember,仅仅是对DataRow执行一个ToString()的方法,所以速度快。可是设置了DM之后,就需要从DataRow提取数据,这个过程存在一定的开销,当你的数据达到10W的时候,时间也随之放大。
      

  7.   

    做完一个操作后用Application.DoEvents()下
      

  8.   


    4楼正解   刚刚在机器上测试了下, 即使不使用多线程操作,只需要在for循环里调用DoEvents就可以实现楼主希望实现的功能
      

  9.   

    真正的问题在于绑定这个过程的实现
    你的绑定是把所有的数据都读入了内存吧?
    要看封装的实现了,这个设计本身就存在这个缺陷,不管你用不用线程。
    因为ComboBox这个控件的内部UI消息一定是在主线程进行处理的,这个是UI的工作。不管.net如何封装,目前依然依赖Windows底层的实现。
    在SDK的程度上理解这个问题就知道了,ComboBox的很多操作都是通过消息来控制。如果你想优化,需要改变你的绑定设计思路,当一个数据源存在大量记录的时候,绑定不应当把左右的数据都加载,你需要优化你的数据源访问方式,而不是UI的部分
      

  10.   

    真正的问题在于绑定这个过程的实现 
    你的绑定是把所有的数据都读入了内存吧? 
    要看封装的实现了,这个设计本身就存在这个缺陷,不管你用不用线程。 
    因为ComboBox这个控件的内部UI消息一定是在主线程进行处理的,这个是UI的工作。不管.net如何封装,目前依然依赖Windows底层的实现。 
    在SDK的程度上理解这个问题就知道了,ComboBox的很多操作都是通过消息来控制。 如果你想优化,需要改变你的绑定设计思路,当一个数据源存在大量记录的时候,绑定不应当把左右的数据都加载,你需要优化你的数据源访问方式,而不是UI的部分 
    up
      

  11.   

    1、ComboBox显示的数据过百的话都是不便查看和选择,应该改变数据的呈现方式.
    2、如果是连动显示数据,也应该只将符合条件的筛选出来,而不是加载全部数据。
      

  12.   

    你应该进行判断一下:
     if(InvokedRequst)//自己查
    {
      beginInvoke(参数);
    }
    else
    {
      你要执行的操作!;
    }
      

  13.   

    3个创建线程应该放入到RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)执行,
    而不是放在_DoWork(object sender, DoWorkEventArgs e)里面,放在里面相当于4个线程一起执行