1. ホーム
  2. c#

[解決済み】クロススレッド操作が有効でない。コントロール 'textBox1' が作成されたスレッド以外のスレッドからアクセスされた [duplicate] 。

2022-04-11 04:42:42

質問

マイコンからUARTで温度値を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' が作成されたスレッド以外のスレッドからアクセスされた。 をクリックします。 マイコンから温度文字列を取得し、このエラーを除去する方法を教えてください。

解決方法を教えてください。

で受信したデータは serialPort1_DataReceived メソッドは、UIスレッドとは別のスレッドコンテキストから来ており、それがこのエラーを表示する理由です。

これを解決するには、MSDN の記事で説明されているように、ディスパッチャを使用する必要があります。

方法 Windowsフォームのコントロールにスレッドセーフな呼び出しをする

そのため、textプロパティを直接 serialport1_DataReceived メソッドで、このパターンを使用します。

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());
}