【发布时间】:2016-05-07 06:42:04
【问题描述】:
我在使用委托从不是主窗体线程的线程中更改 Textbox 时遇到问题。
我有两个类,一个带有 UI 的主 Form1.cs 类和另一个类 LINClass.cs,我在其中编写了一个设备函数。 在 Form1 中,我启动了一个不断轮询设备的后台工作程序,以及另一个从设备中检索数据的线程(RXTask()),这两个线程的所有功能都来自 LINCLass.cs。
从设备检索数据的线程包含一个委托,该委托指向允许更改 Form1 文本框的 Form1.cs 函数:
public class LINClass : Form
{
private delegate void FormUpdater(int devnum, string rpm, string current, string temp);
//some other variables and procedure
public void RXTask()
{
FormUpdater frmUpdt = new FormUpdater(Form1.GUIupdate);
//other procedures and a loop containing the invoke...
this.Invoke(frmUpdt, new object[]{devnum, rpm,
current,
temperature});
}
Form1类包含调用的方法,写法如下
public static void GUIupdate(int eWPnum, string rpm, string current, string temp)
{
//take the parameters and write them in the textbox
}
现在,当我运行代码时,线程正在运行,但调用函数时出现异常。
http://s13.postimg.org/9ohuj9d7r/exception.png
它说,“InvalidOperationException 未被管理,在创建窗口句柄之前不能在控件上调用 Invoke 或 BeginInvoke”
【问题讨论】:
-
这是一个众所周知的问题。您需要谷歌 BeginInvoke 以获得规范的解决方案。基本上,您必须检查是否需要调用,如果是,则使用相同的参数调用它并停止在错误的线程上执行。
-
您可能在表单的
Initialize()方法完成运行之前调用了该方法。如果文本框尚未添加到 from 的控件集合中,您将收到此错误。 -
Windows 不是实时操作系统;您确定要尝试连续轮询设备吗?您是否愿意加热整个 CPU 以除此之外什么都不做?我的笔记本电脑的电池寿命不会感谢你。为什么不在一个线程上做所有事情并异步处理设备,而不是同时处理?
-
谢谢大家的建议,此时我在执行调用的代码之前用“蛮力”this.CreateHandle() 解决了这个问题,在这段代码之后用this.DestroyHandle() 解决了每个循环GUI 的句柄被创建和删除...
标签: c# multithreading