我的程序的一部分为我的串行端口的接收数据使用了一个事件处理程序。其想法是,当接收到数据时,接收到的文本将添加到文本框(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未处理:从创建线程以外的线程。
从我所能读到的内容来看,我需要使用invoke
或BeginInvoke
。
我以前从未遇到过添加文本的问题,所以现在我不明白为什么这是一个问题。同样,从我读到的关于调用的内容来看,我只是不明白。
有人能帮我理解如何在我的情况下使用invoke实例吗?或者给我看另一种附加文本框的方法?
通常在调试模式下运行时会出现异常,如果在发布模式下运行应用程序,则不太可能出现异常。
不过,正如您所阅读的,最好使用invoke。类似这样的东西:
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);
}
当你第一次看到这种调用的东西时,几乎不可能遵循,但仔细观察并给它一些时间,它就会有意义。承诺。:)
GUI应用程序中的更新只能在GUI线程上完成。另一个试图直接更新GUI组件的线程将导致您描述的错误或看似随机的行为。
Invoke
&friends是使辅助线程能够安全地将GUI更新转发到GUI线程,然后GUI线程将从队列中处理这些更新。
在您的情况下(假设此处为WinForms):
rx.BeginInvoke(
(Action)(() =>
{
rx.AppendText(Environment.NewLine + indata1);
}));
BeginInvoke
是异步的,因此调用它的线程不会等待实际更新处理后再继续,而Invoke
是同步的。