【问题标题】:Cross-threading operation not valid [duplicate]跨线程操作无效[重复]
【发布时间】:2012-08-22 21:59:43
【问题描述】:

可能重复:
Why am I getting this error:“Cross-thread operation not valid: Control lbFolders accessed from a thread other than the thread it was created on.”?
Invoke or BeginInvoke cannot be called on a control until the window handle has been created

我的线程有问题。

我每 600 毫秒从 COM 端口获取数据,当我处于调试模式时,我会在几秒钟后收到错误消息,但是当我处于非调试运行模式时,我会在一两分钟后收到错误消息,但错误仍然存​​在。

我得到的错误发生在每个线程上调用的某些函数上。

这是错误的图片:

其他部分代码:

private void LoadData()
        {
            while (td.IsAlive)
            {
                eng.GetSpeedKmh();
                eng.GetEngineRpm();
                eng.GetCalculatedEngineLoadValue();
                eng.GetFuelLevelInput();
                eng.GetEngineTemp();
                eng.MAF();

                System.Threading.Thread.Sleep(600);
            }
        }

我能做些什么来解决这个问题?

【问题讨论】:

标签: c# multithreading


【解决方案1】:

调用 .Text 属性的编辑:

this.Invoke((MethodInvoker) delegate { brzina_ele.Text = "Its new value"; });

您还可以使用 Windows.Forms.Timer 的 Tick 事件进行调用。这更加线程安全,并且拥有您需要的一切。

【讨论】:

  • -1:您的答案是 NeerajKaushik. 先前答案的非常有限的副本,他提出了一种可重复使用的“bouncemeback”方法。您已尝试添加另一个选项,但您建议的不是很有用 - 看看问题:他使用 COM 端口,他提供的代码是一个类似异步的回调“On - GetSpeed - Done”,所以他可能有一个带有超时阻塞读取的 bgthread。 “OBD”也暗示了这一点。建议将异步转换为 UI 绑定回调(因此,轮询会阻塞 UI)对我来说似乎不太合理..
【解决方案2】:

试试下面的代码

public void eng_OnGetSpeedDone(OBDIIEngineEventArgs args)
        {
            if (this.InvokeRequired)
            {
                Action action = () => eng_OnGetSpeedDone(args);
                Invoke(action);
                return;
            }
            if (!args.OBDResultNoData)
                brzina_ele.Text = arg.OBDValue.ToString();
            else
                brzina_ele.Text = "0";

        }

【讨论】:

  • 你能解释一下这段代码吗
  • 因为 Winforms 在 STA 上工作,所以跨线程操作应该编组到主 UI 线程以在 UI 上绘制.... InvokeRequired 是 UI 控件的属性,有助于检查调用是否为跨线程。要编组跨线程调用,您可以使用 Invoke 或 BeginInvoke 方法,这将编组对 UI 线程的调用...调用方法期望委托作为参数,委托应该与您的方法具有相同的签名...我使用带有 lambda 表达式的 Action 委托来创建委托实例..然后调用 Invoke 方法在 UI 线程上调用相同的方法。
  • 如果你想要异步操作,那么你可以使用 BeginInvoke 而不是 Invoke。
  • 哪个更适合我?开始调用还是调用?顺便提一句。现在我没有那个错误,所以这有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
相关资源
最近更新 更多