跨线程:从不同的线程访问控件

时间:2013-02-06 12:56:32

标签: c# .net winforms multithreading

我认为代码说明清楚

private void ucPerson_Load(object sender, EventArgs e)
{
    person = new Person();
    BackgroundWorker backgroundBinder = new BackgroundWorker();
    backgroundBinder.DoWork += BindComboBoxes;
    backgroundBinder.RunWorkerAsync();
}

private void BindComboBoxes(object sender, DoWorkEventArgs e)
{
    cmbEducationLevel.DataSource = Program.eService.GetEducationLevels();
    cmbNationality.DisplayMember = "Name";
    cmbNationality.ValueMember = "NationalityID";
}

我得到错误:

  

跨线程操作无效:控制从创建它的线程以外的线程访问“cmbNationality”。

我需要做些什么才能让background-worker的线程访问组合框?

3 个答案:

答案 0 :(得分:3)

backgroundworker在另一个线程中工作:不允许调用属于其中调用线程的控件。

正如Uwe Keim所说,你必须在RunWorkerCompleted事件中放置触及控件的所有内容:

private void ucPerson_Load(object sender, EventArgs e)
{
    person = new Person();
    BackgroundWorker backgroundBinder = new BackgroundWorker();
    backgroundBinder.DoWork += GetData;
    backgroundBinder.RunWorkerCompleted += BindComboBoxes;
    backgroundBinder.RunWorkerAsync();
}

<<yourReturnType>> source;

private void GetData(object sender, DoWorkEventArgs e)
{
    source = Program.eService.GetEducationLevels();
}

private void BindComboBoxes(object sender, RunWorkerCompletedEventArgs e)
{
    cmbNationality.DisplayMember = "Name";
    cmbNationality.ValueMember = "NationalityID";
    cmbNationalty.DataSource = source;
}

答案 1 :(得分:0)

最好的方式是Laurent的例子

肮脏的方式:

cmbEductionLevel.Invoke((MethodInvoker)delegate { mbEducationLevel.DataSource = Program.eService.GetEducationLevels(); });

cmbNationality.Invoke((MethodInvoker)delegate { 
     cmbNationality.DisplayMember = "Name";
     cmbNationality.ValueMember = "NationalityID"; 
});

答案 2 :(得分:-1)

您应该使用Invoke并传递委托以更新控件。