VB / C#.net使用后台工作者

时间:2016-03-27 18:55:52

标签: c# vb.net multithreading winforms

我正在创建一个Windows窗体应用程序,它根据从数据库中提取的数据动态创建控件。

我的代码在后台运行很好,它从数据库加载数据并将其应用于变量,我遇到的问题是当尝试使用这些数据创建控件时,我得到一个多线程错误(附加信息:跨线程操作无效:控制' flowpanelMenuRules'从其创建的线程以外的线程访问。)

我使用BackgroundWorker_DoWork事件,失败的代码如下:

Me.flowpanelMenuRules.Controls.Add(PanelRule(i))

之前的代码是一个简单的循环,通过变量(从数据库中提取)并收集信息。

有没有人有安全调用上述线路的经验?我似乎无法让它完全发挥作用:(

感谢您的帮助,如果需要,我可以发布更多代码。

2 个答案:

答案 0 :(得分:6)

我的建议是让BackgroundWorker只创建控件,但不要将它们添加到表单中。而是通过RunWorkerCompleted事件将准备好的控件返回到调用/ UI线程。然后在此时将控件添加到表单中,可能与SuspendLayout() / ResumeLayout()方法结合使用。

答案 1 :(得分:1)

WinForms应用程序的本机方法是使用System.Winfows.Forms.ControlInvoke()属性等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)));