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

本文关键字:线程 访问 控件 | 更新日期: 2023-09-27 17:58:03

我认为代码可以清除

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的线程访问组合框?

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

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

正如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;
}

最好的方法是Laurent 的例子

肮脏的方式:

cmbEductionLevel.Invoke((MethodInvoker)delegate { mbEducationLevel.DataSource = Program.eService.GetEducationLevels(); });
cmbNationality.Invoke((MethodInvoker)delegate { 
     cmbNationality.DisplayMember = "Name";
     cmbNationality.ValueMember = "NationalityID"; 
});

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