【问题标题】:VB/C#.net Dynamically Add Control Items with Background WorkerVB/C#.net 使用后台 Worker 动态添加控件项
【发布时间】:2016-03-27 18:55:51
【问题描述】:

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

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

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

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

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

有没有人有任何安全调用上述行的经验?我似乎根本无法让它工作:(

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

【问题讨论】:

  • 请参阅stackoverflow.com/questions/142003/… 了解问题所在。
  • 控件不应在后台线程上创建。它们被分配给创建它们的线程,并且只能在那里使用。您应该调用控件的具体创建和更新,其余的可以在 BGW 中完成。

标签: c# vb.net multithreading winforms


【解决方案1】:

我的建议是让您的 BackgroundWorker 简单地创建控件,而不是将它们添加到表单中。相反,通过RunWorkerCompleted 事件将准备好的控件返回给调用/UI 线程。然后此时将控件添加到您的表单中,可能与SuspendLayout()/ResumeLayout() 方法一起使用。

【讨论】:

  • Joel - 我使用了这个想法,并且效果很好。我现在让后台工作人员运行我的 SQL 代码,将数据库中的信息提取到变量中,然后使用后台工作人员完成事件将结果填充到 FlowLayoutPanel 中。谢谢!我以前使用过后台工作人员,但由于某种原因,已完成的事件让我忘记了
【解决方案2】:

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)));

【讨论】:

  • 您是否在混合使用 VB 和 C#?
  • @Rinecamo 这个问题是用 C# 标签提出的,我所有的例子都只包含 c# 代码。
  • Me 是 VB 等价于 this ;)
  • @Rinecamo 哦,哇,谢谢,我编辑了我的答案。我以为Me是属性名。
猜你喜欢
  • 2013-02-26
  • 1970-01-01
  • 2012-12-10
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 2011-01-05
相关资源
最近更新 更多