首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >线程间操作无效:控件“textBox1”是从创建该控件的线程以外的线程访问的

线程间操作无效:控件“textBox1”是从创建该控件的线程以外的线程访问的
EN

Stack Overflow用户
提问于 2012-05-28 00:05:49
回答 6查看 403.2K关注 0票数 210

我想用串口将单片机的温度值送到C#接口,并在Label.Content上显示温度。这是我的微控制器代码:

while(1) {
   key_scan(); // get value of temp
   if (Usart_Data_Ready())
   {
      while(temperature[i]!=0)
      {
         if(temperature[i]!=' ')
         {
            Usart_Write(temperature[i]);
            Delay_ms(1000);
         }
         i = i + 1;
      }
      i =0;
      Delay_ms(2000);
   }
}

我的C#代码是:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
   txt += serialPort1.ReadExisting().ToString();
   textBox1.Text = txt.ToString();
}

但出现异常“跨线程操作无效:控件'textBox1‘是从上创建的线程以外的线程访问的”请告诉我如何从我的微控制器获取温度字符串并消除此错误!

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-05-28 00:15:15

在您的serialPort1_DataReceived方法中接收的数据来自另一个线程上下文,而不是UI线程,这就是您看到此错误的原因。

要解决此问题,您必须使用MSDN文章中描述的调度程序:

How to: Make Thread-Safe Calls to Windows Forms Controls

因此,不要直接在serialport1_DataReceived方法中设置text属性,请使用以下模式:

delegate void SetTextCallback(string text);

private void SetText(string text)
{
  // InvokeRequired required compares the thread ID of the
  // calling thread to the thread ID of the creating thread.
  // If these threads are different, it returns true.
  if (this.textBox1.InvokeRequired)
  { 
    SetTextCallback d = new SetTextCallback(SetText);
    this.Invoke(d, new object[] { text });
  }
  else
  {
    this.textBox1.Text = text;
  }
}

所以在你的例子中:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
  txt += serialPort1.ReadExisting().ToString();
  SetText(txt.ToString());
}
票数 346
EN

Stack Overflow用户

发布于 2013-04-05 18:12:49

我不知道这是否足够好,但是我做了一个静态的ThreadHelperClass类,并按照下面的.Now实现了它,我可以很容易地设置各种控件的文本属性,而不需要太多的编码。

public static class ThreadHelperClass
{
    delegate void SetTextCallback(Form f, Control ctrl, string text);
    /// <summary>
    /// Set text property of various controls
    /// </summary>
    /// <param name="form">The calling form</param>
    /// <param name="ctrl"></param>
    /// <param name="text"></param>
    public static void SetText(Form form, Control ctrl, string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (ctrl.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            form.Invoke(d, new object[] { form, ctrl, text });
        }
        else
        {
            ctrl.Text = text;
        }
    }
}

使用以下代码:

 private void btnTestThread_Click(object sender, EventArgs e)
 {
    Thread demoThread =
       new Thread(new ThreadStart(this.ThreadProcSafe));
            demoThread.Start();
 }

 // This method is executed on the worker thread and makes 
 // a thread-safe call on the TextBox control. 
 private void ThreadProcSafe()
 {
     ThreadHelperClass.SetText(this, textBox1, "This text was set safely.");
     ThreadHelperClass.SetText(this, textBox2, "another text was set safely.");
 }
票数 58
EN

Stack Overflow用户

发布于 2012-11-27 03:27:43

你可以简单地做到这一点。

TextBox.CheckForIllegalCrossThreadCalls = false;
票数 39
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10775367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档