使用委托进行交叉线程的 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"

使用委托进行交叉线程的 C# 时遇到问题

您应该使用命令模式并将命令类从一个线程放入队列中,并让另一个线程从中读取。

除非

已创建窗体的窗口,否则您需要防止调用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