[英]How to update some GUI control in a WinForm from another thread in C# using async
我正在尝试从第二个线程更新某些GUI控件的文本,但是Visual Studio显示了一个异常:
System.Windows.Forms.dll中发生类型为“ System.InvalidOperationException”的异常,但未在用户代码中处理
附加信息:
通过子流程进行的无效操作:对“ impPROF_combo”的访问从他创建的线程之外的其他线程获得了控制权。
我的代码是:
private async void checkBox1_CheckedChanged(object sender, EventArgs e)
{
sciLoadingCircle1.Visible = true;
sciLoadingCircle1.Active = true;
await Task.Run(() => refreshComboColumnsNames());
sciLoadingCircle1.Visible = false;
sciLoadingCircle1.Active = false;
}
private void refreshComboColumnsNames()
{
object[] columnsNames = this.generateComboColumnsNames();
int impPROF_combo_selected = impPROF_combo.SelectedIndex; //the exceptions throws from here
impPROF_combo.Items.Clear();
impPROF_combo.Items.AddRange(columnsNames);
impPROF_combo.SelectedIndex = impPROF_combo_selected;
}
我怎样才能正确地做到这一点? 谢谢。
UI组件只能从其UI线程访问。 在这种情况下,您将在Task.Run
放入太多代码:
private async void checkBox1_CheckedChanged(object sender, EventArgs e)
{
sciLoadingCircle1.Visible = true;
sciLoadingCircle1.Active = true;
await refreshComboColumnsNamesAsync();
sciLoadingCircle1.Visible = false;
sciLoadingCircle1.Active = false;
}
private async Task refreshComboColumnsNamesAsync()
{
object[] columnsNames = await Task.Run(() => this.generateComboColumnsNames());
int impPROF_combo_selected = impPROF_combo.SelectedIndex;
impPROF_combo.Items.Clear();
impPROF_combo.Items.AddRange(columnsNames);
impPROF_combo.SelectedIndex = impPROF_combo_selected;
}
为了从另一个线程更新GUI(或使用)元素,您应该使用Control.BeginInvoke() https://msdn.microsoft.com/ru-ru/library/system.windows.forms.control.begininvoke ( v= vs .110).aspx,以及如何使用它。 如何使用BeginInvoke C#
您想要在GUI线程以外的线程中执行某些代码的通常原因是,该操作需要大量时间才能完成并阻塞GUI线程。
我可以看到refreshComboColumnsNames
方法的代码的唯一线,这可能需要时间- generateComboColumnsNames
。 其他语句是GUI更新操作,必须在GUI线程中执行。 据我了解, generateComboColumnsNames
做一些繁重的计算或执行数据库查询或发送http请求或执行任何其他长操作。 此操作的结果需要在UI中显示。 纠正我,如果我错了。
我建议使generateComboColumnsNames
异步运行,该操作在单独的线程中执行。 此操作不得更新UI-仅返回数据。 结果如下所示:
private async void checkBox1_CheckedChanged(object sender, EventArgs e)
{
sciLoadingCircle1.Visible = true;
sciLoadingCircle1.Active = true;
await refreshComboColumnsNames();
sciLoadingCircle1.Visible = false;
sciLoadingCircle1.Active = false;
}
private async Task refreshComboColumnsNames()
{
object[] columnsNames = await this.generateComboColumnsNames();
int impPROF_combo_selected = impPROF_combo.SelectedIndex;
impPROF_combo.Items.Clear();
impPROF_combo.Items.AddRange(columnsNames);
impPROF_combo.SelectedIndex = impPROF_combo_selected;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.