从Backgroundworker DoWork访问窗口控制
我的问题如下:
我有一个 Windows 窗体,其中放置了 LayoutPanel,当窗体加载时,多个控件(例如:文本框和标签)将添加到 LayoutPanel。
然后,单击按钮后,我需要处理用户在这些动态创建的控件上输入的数据。为此,我使用了一个后台工作者,它应该接受这些控件并读取它们的数据。
我的问题是,Backgroundworker 不允许我从 DoWork 方法访问控件,但我需要这样做,因为我将报告操作的进度。
以下是我的代码的一部分,用于澄清这个概念:
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.
}
}
设置文本很简单,只需使用委托,但是如何让整个父控件来操作子控件(只是为了获取信息,我不想设置任何数据,只是需要获取名称、文本等信息)。
希望我说清楚了,谢谢大家。
my issue is the following:
I have a windows form in which I've placed a LayoutPanel, when the forms Loads, multiple controls like: textboxes and labels are being added to the LayoutPanel.
Then on a button click, I need to process the data entered by the user on those dynamically created controls. For that purpouse I use a Backgroundworker which is supposed to take those controls and read their data.
My issue es that the Backgroundworker doesn't allows me to access the control from the DoWork Method, but I need to do it that way because I'll be reporting the progress of the operations.
Here are portions of my code to clarify the concept:
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.
}
}
Setting text is simple just using a delegate, but how about getting the entire parent control to manipulate the child controls (just for getting info, I don't want to set any data, just need to Get Name, Text, stuff like that).
Hope I made myself clear, thank you all.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您只能从 GUI 线程访问 Windows 窗体控件。如果您想从另一个线程操作它们,则需要使用 Control.Invoke 方法传入委托以在 GUI 线程上执行。在您的情况下,您应该能够执行以下操作:
我喜欢定义一个扩展方法,允许我使用更清晰的 lambda 语法:
You can only access Windows Forms controls from the GUI thread. If you want to manipulate them from another thread, you will need to use the Control.Invoke method to pass in a delegate to execute on the GUI thread. In your situation, you should be able to do this:
I like to define an extension method that allows me to use the cleaner lambda syntax:
正如您所知,从 UI 线程以外的任何线程访问控制值是一个很大的禁忌。我认为一种合理的实现是使用 .NET 同步机制(例如 WaitHandle)来挂起后台线程,同时 UI 线程更新您选择的线程安全数据结构。
这个想法是,您的后台线程通知 UI 线程(通过您已经熟悉的委托机制)它需要信息,然后等待。当 UI 完成用信息填充共享变量时,它会重置 WaitHandle,并且后台工作程序将恢复。
在不编写和测试所有代码的情况下,让我给您一些资源:
As you are already aware, accessing control values from any thread other than the UI thread is a big no-no. I'd say one reasonable implementation is to use a .NET synchronization mechanism, such as a WaitHandle, to suspend your background thread while the UI thread updates a thread-safe data structure of your choice.
The idea is that your background thread notifies the UI thread (via the delegate mechanism you are already familiar with) that it needs information, then waits. When the UI is finished populating the shared variable with information, it resets the WaitHandle, and the background worker resumes.
Without writing out and testing all the code, let me give you a few resources: