Winforms 从Backgroundworker DoWork访问windows控件
我的问题如下: 我有一个windows窗体,我在其中放置了一个布局面板,当窗体加载时,多个控件(如:文本框和标签)将添加到布局面板 然后单击按钮,我需要处理用户在这些动态创建的控件上输入的数据。出于这个目的,我使用了一个后台工作人员,该人员负责获取这些控件并读取它们的数据 我的问题是Backgroundworker不允许我从DoWork方法访问控件,但我需要这样做,因为我将报告操作的进度 以下是我的代码中澄清概念的部分:Winforms 从Backgroundworker DoWork访问windows控件,winforms,backgroundworker,Winforms,Backgroundworker,我的问题如下: 我有一个windows窗体,我在其中放置了一个布局面板,当窗体加载时,多个控件(如:文本框和标签)将添加到布局面板 然后单击按钮,我需要处理用户在这些动态创建的控件上输入的数据。出于这个目的,我使用了一个后台工作人员,该人员负责获取这些控件并读取它们的数据 我的问题是Backgroundworker不允许我从DoWork方法访问控件,但我需要这样做,因为我将报告操作的进度 以下是我的代码中澄清概念的部分: private void frmMyForm_Load(object se
private void frmMyForm_Load(object sender, EventArgs e)
{
//I add multiple controls, this one is just for example
LayoutPanel1.add(TextBox1);
....
}
private void bgwBackground_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Control controlOut in LayoutPanel1.Controls)
{
//do some stuff, this one is just for example
string myString = controlOut.Name; //-> Here is the error, cant access controls from different Thread.
}
}
使用委托设置文本很简单,但是让整个父控件操作子控件如何(只是为了获取信息,我不想设置任何数据,只需要获取名称、文本之类的内容)
希望我说清楚,谢谢大家。正如大家已经知道的,从UI线程以外的任何线程访问控制值都是一个大禁忌。我想说一个合理的实现是使用.NET同步机制,例如WaitHandle,在UI线程更新您选择的线程安全数据结构时挂起后台线程 其思想是,后台线程通知UI线程(通过您已经熟悉的委托机制)它需要信息,然后等待。当UI用信息填充完共享变量后,它将重置WaitHandle,后台工作程序将继续 在不编写和测试所有代码的情况下,让我为您提供一些参考资料:
- WaitHandle.WaitOne文档及其用法示例:
- 我自己最喜欢的在UI线程上调用事件的方法:
private void bgwBackground_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Control controlOut in LayoutPanel1.Controls)
{
this.Invoke(new MethodInvoker(delegate {
// Execute the following code on the GUI thread.
string myString = controlOut.Name;
}));
}
}
我想定义一个扩展方法,允许我使用cleaner lambda语法:
// Extension method.
internal static void Invoke(this Control control, Action action) {
control.Invoke(action);
}
// Code elsewhere.
this.Invoke(() => {
string myString = controlOut.Name;
});