-3

내 주 WindowsForm에서이 코드를 실행하려고하면 다음 예외가 발생합니다.

처리되지 않은 'System.InvalidOperationException'형식의 예외가 System.Windows.Forms.dll에서 발생했습니다. 추가 정보 : 교차 스레드 조작이 유효하지 않음 : 작성된 스레드가 아닌 다른 스레드에서 액세스 한 'richTextBox1'제어.

이벤트, 이벤트 핸들러 및 스레드에 대해 많이 알게되었습니다. 그러나 이벤트와 함께 직접 작업하거나 멀티 스레드를 수동으로 생성하는 방법에 대해서는 깊이 생각해 보지 못했습니다. MSDN에서이 기사를 찾았습니다.

-> 링크 -그러나 나는 그것을 정말로 이해하지 못했다. richtextbox1에 출력을 쓰려고하면 오류가 나타납니다.

SerialPort Arduino = new SerialPort();
    public Form1()
    {
        InitializeComponent();
        this.Load += Form1_Load;

    }

    void Form1_Load(object sender, EventArgs e)
    {
      string[] k = SerialPort.GetPortNames();
      cBPortWaehlen.DataSource = k;

    } 
    private void btnOpenPort_Click(object sender, EventArgs e)

    {
        if (!Arduino.IsOpen)
        {
            Arduino.DataReceived += Arduino_DataReceived;
            Arduino.BaudRate = 115200;
            Arduino.PortName = cBPortWaehlen.SelectedItem.ToString();
            Arduino.Open();
        }
        else
        {
            MessageBox.Show("Port schon offen");
        }

    }

    private void Arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
            this.richTextBox1.AppendText(Arduino.ReadExisting());

    }

    private void btnClosePort_Click(object sender, EventArgs e)
    {
        Arduino.Close();

    }

2 답변


3

데이터를받을 때

private void Arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
        this.richTextBox1.AppendText(Arduino.ReadExisting());

}

이 이벤트는 Arduino를 모니터링하는 다른 스레드에서 발생합니다.

기본적으로 winforms 응용 프로그램에는 하나 이상의 스레드 (UI 스레드)가 있습니다. 해당 스레드에서 코드를 실행하면 UI가 중단되어 응답하지 않게됩니다.

따라서 UI가 응답하는 동안 백그라운드에서 일이 일어나기를 원하면 별도의 스레드에서 수행해야합니다.

불행하게도 (실제로는 sevaral 한 이유로) 스레드는 서로의 참조를 사용할 수 없습니다.

그러나 그들은 서로 메시지를 보낼 수 있습니다.

그 중 하나는 특정 작업을 호출하기위한 요청입니다. Windows Forms에는이 기능을 사용하기위한 몇 가지 편리한 메서드가 있습니다.

private void Arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
        if(richTextBox1.InvokeRequired)
        {
            richTextBox1.Invoke(
               (Action)delegate 
               { 
                 richTextBox1.AppendText(Arduino.ReadExisting()); 
               }
            );
        }
}


  • 호출이 필요한지 확인하는 이유는 무엇입니까?알고있다호출이 필요합니까? 글쓰기와 같아요.if(true)귀하의 코드입니다. - Servy
  • @Servy 컴파일러 / 지터가이를 실현하고 명세서를 제거했는지 알아 보는 것은 흥미 롭습니다 ... - James Thorpe
  • 물론 할 수는 없습니다.그것그렇게해도 이벤트가 항상 다른 스레드에서 시작된다는 것을 알 수 없습니다. - Servy
  • @Servy 아 물론. 나는 그것을 최적화하는 생각이라고 생각합니다.if (true)그 생각을하게 :) - James Thorpe

1

UI 스레드 만 사용하여 양식을 업데이트하는지 확인하십시오. UI 구성 요소 (예 : this.richTextBox1.AppendText)의 속성에 대한 액세스를 설정할 때마다 UI 스레드에 위임한다는 점에주의해야 크로스 스레드 예외가 발생하지 않습니다.

당신은 다음과 같이 할 수 있습니다 :

delegate void UpdateDelegate(string text);

private void UpdateInformation(string text)
{
   if(this.InvokeRequired)
   {
      UpdateDelegate ud = new UpdateDelegate(UpdateInformation);
      this.BeginInvoke(ud, new object[] { text } );
   }
   else 
   {
      this.myTextBox.Text = text;
   }
}

익명의 위임자를 사용할 수도 있지만 위의 내용은 이해하기가 더 쉽습니다.

연결된 질문


관련된 질문

최근 질문