使用委托进行交叉线程的 C# 时遇到问题
本文关键字:线程 问题 遇到 | 更新日期: 2023-09-27 18:32:30
我在使用委托从不是主表单线程的线程更改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"
您应该使用命令模式并将命令类从一个线程放入队列中,并让另一个线程从中读取。
除非
已创建窗体的窗口,否则您需要防止调用this.Invoke()
。
最简单的方法是覆盖OnLoad()
并设置一个标志:
private bool isLoaded;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Volatile.Write(ref isLoaded, true);
}
然后在调用之前检查标志:
public void RXTask()
{
FormUpdater frmUpdt = new FormUpdater(Form1.GUIupdate);
//other procedures and a loop containing the invoke...
if (Volatile.Read(ref isLoaded))
{
this.Invoke(frmUpdt, new object[]
{
devnum, rpm,
current,
temperature
});
}
}
(如果您的 .Net 版本没有 Volatile.Read()/Volatile.Write(),请将标志声明为 volatile
。