我正在创建一个Windows窗体应用程序,它根据从数据库中提取的数据动态创建控件。
我的代码在后台运行很好,它从数据库加载数据并将其应用于变量,我遇到的问题是当尝试使用这些数据创建控件时,我得到一个多线程错误(附加信息:跨线程操作无效:控制' flowpanelMenuRules'从其创建的线程以外的线程访问。)
我使用BackgroundWorker_DoWork事件,失败的代码如下:
Me.flowpanelMenuRules.Controls.Add(PanelRule(i))
之前的代码是一个简单的循环,通过变量(从数据库中提取)并收集信息。
有没有人有安全调用上述线路的经验?我似乎无法让它完全发挥作用:(
感谢您的帮助,如果需要,我可以发布更多代码。
答案 0 :(得分:6)
我的建议是让BackgroundWorker只创建控件,但不要将它们添加到表单中。而是通过RunWorkerCompleted
事件将准备好的控件返回到调用/ UI线程。然后在此时将控件添加到表单中,可能与SuspendLayout()
/ ResumeLayout()
方法结合使用。
答案 1 :(得分:1)
WinForms应用程序的本机方法是使用System.Winfows.Forms.Control
和Invoke()
属性等InvokeRequired
方法来访问UI线程:
if(this.flowpanelMenuRules.InvokeRequired)
{
this.flowpanelMenuRules.Invoke(() => AddPanelRule());
}
else
{
AddPanelRule();
}
您也可以使用Dispatcher
课程。
如果你确定要在UI线程上(例如在一个button.Click处理程序中),Dispatcher.CurrentDispatcher
会为你提供一个UI线程调度程序,你可以在以后用它像往常一样从后台线程调度到UI线程
Dispatcher.CurrentDispatcher.Invoke(() => this.flowpanelMenuRules.Controls.Add(PanelRule(i)));