4

我的部分程序使用事件处理程序来接收串行端口的数据。这个想法是在接收到数据时将接收到的文本添加到文本框(rx)中。我以前没有这个问题,但有些东西已经改变了,我不知道是什么。所以现在我正在重新审视这个处理方式。

在我的 winform 表单加载期间,我做的最后一件事是

if (!serialPort1.IsOpen)
{
     serialPort1.Open();
     serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}

然后我有事件处理程序

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
     string indata1 = serialPort1.ReadExisting();
    // rx.Text = " "; accidentally posted this. it was from trial and error.  
     rx.AppendText(Environment.NewLine + indata1);
}

当我运行程序时,它停在rx.AppendText(Environment.NewLine + indata1);并给出错误

invalidoperationexception 未处理:控制“从创建它的线程以外的线程访问。

从我能够阅读的内容来看,我需要使用invokeor BeginInvoke

我以前从未遇到过附加文本的问题,所以现在我不明白为什么会出现问题。另外,从我一直在阅读的关于调用的内容来看,我只是不明白。

有人可以帮助我了解如何针对我的情况使用调用实例吗?或者也许向我展示另一种附加文本框的方式?

4

2 回答 2

6

通常,您看到的异常发生在您以调试模式运行时,如果您以发布模式运行应用程序,则不太可能看到该异常。

但是,正如您所阅读的,最好使用调用。像这样的东西:

    private delegate void RefreshTextBox();

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
        //this event is raised in an event separate from UI thread, 
        //so InvokeRequired must be checked and Invoke called to update UI controls. 
        if (this.InvokeRequired) {
            RefreshTextBox d = new RefreshTextBox(RefreshTextBoxResults);
            Invoke(d);
        } else {
            RefreshTextBoxResults();
        }
    }

    private void RefreshTextBoxResults() {
        string indata1 = serialPort1.ReadExisting();
        rx.Text = " ";
        rx.AppendText(Environment.NewLine + indata1);
    }

当你第一次看到这个调用的东西时,几乎不可能理解,但仔细看看并给它一些时间,它会很有意义。承诺。:)

于 2012-08-22T20:19:47.577 回答
5

GUI 应用程序中的更新只能在 GUI 线程上完成。另一个尝试直接更新 GUI 组件的线程将导致您描述的错误或看似随机的行为。

&friends的作用Invoke是使辅助线程能够安全地将 GUI 更新转发到 GUI 线程,该线程随后将从队列中处理它们。

在您的情况下(假设此处为 WinForms):

rx.BeginInvoke(
      (Action)(() =>
      {
          rx.AppendText(Environment.NewLine + indata1);
      }));

BeginInvoke是异步的,所以调用它的线程在继续之前不会等待实际更新被处理,而Invoke它是同步的。

于 2012-08-22T20:18:42.817 回答