【问题标题】:c# cross-thread error with UserControlsc# UserControls 的跨线程错误
【发布时间】:2010-08-27 03:45:45
【问题描述】:

这是我的情况:

我在主线程上实例化了一个 c# 用户控件,但它没有添加到表单中。

//global declaration
usercontrol1 datacontrol;

 constructor()
{
.......
     datacontrol = new usercontrol1();
........
}

然后我有一个异步后台线程,它触发由实例化数据控件处理的事件。事件处理程序有一个:

if(InvokeRequired){BeginInvoke(..);}

这应该可以防止进行任何跨线程调用。但是,当它被调用时,InvokeRequired 为 false,因此不会在正确的线程上调用处理程序。所以在处理程序中,当我尝试 this.labelname.text ="blah" 时,会引发跨线程异常。

但是,如果我将控件添加到主窗体上的面板并将其删除,则允许后台线程触发事件。处理程序进入,但这次 'InvokeRequired' 设置为 true,因此它在主线程上下文中正确调用自身,避免异常。

有人可以向我解释为什么将其添加到面板然后删除它会修复错误吗?

表单没有 onLoad 事件,因此所有内容都应该在不被绘制的情况下正确实例化。

谢谢! 斯蒂芬妮

【问题讨论】:

  • "将控件添加到面板" = "将数据表单添加到面板?
  • 我的示例命名是一个糟糕的选择,它是一个用户控件而不是一个 winform。更新了示例

标签: c# .net winforms user-controls multithreading


【解决方案1】:

这可能是因为尚未创建控件的句柄。如果您在构造函数中引用dataform.Handle,它应该创建句柄并适当地设置线程ID,因此InvokeRequired 稍后将返回true。

您也可以使用CreateControl 强制创建句柄,但前提是控件可见。

【讨论】:

  • 我的用户控件没有显示 .createHandle() 的选项。 .IsHAndleCreated 确实如此
  • @Without 对不起,CreateHandle 受到保护。您可以在您的控制类中访问它。用另一个替代解决方案更新了答案。不过,只需访问 Handle 属性就可以满足您的需求。
  • 这行得通!太感谢了。我对此感到非常困惑!
  • 只是为了分享我所做的。我在控件的初始声明之后添加了 (!datacontrol.IsHandleCreated) datacontrol.CreateControl()。这似乎已经解决了。再次感谢!
【解决方案2】:

当您将控件(或窗体)添加到父级时,它会设置 WindowHandles 的创建。显然还需要初始化 InvokeRequired 逻辑的执行上下文。

因此,不要假设已创建但从未显示的控件或表单行为“正常”。

【讨论】:

  • 所以你认为没有办法显示控件?
猜你喜欢
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
  • 2011-03-02
相关资源
最近更新 更多