C# 用文本框c调用#

C# 用文本框c调用#,c#,multithreading,visual-studio-2010,event-handling,serial-port,C#,Multithreading,Visual Studio 2010,Event Handling,Serial Port,程序的一部分使用事件处理程序接收串行端口的数据。其思想是当接收到数据时,接收到的文本将被添加到文本框(rx)。我以前没有这个问题,但有些事情已经改变了,我不知道是什么。因此,现在我正在重新检查处理这一问题的方式 在winform的表单加载过程中,我做的最后一件事是 if (!serialPort1.IsOpen) { serialPort1.Open(); serialPort1.DataReceived += new SerialDataReceivedEventHandl

程序的一部分使用事件处理程序接收串行端口的数据。其思想是当接收到数据时,接收到的文本将被添加到文本框(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实例吗?或者给我演示另一种附加文本框的方法吗?

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

Invoke
&friends的作用是使辅助线程能够安全地将GUI更新转发给GUI线程,然后GUI线程将从队列中处理这些更新

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


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

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

所以这是有意义的。我实际上是在另一台计算机上运行这个应用程序。所以当我发布它并把它带到那台机器上时,它工作了。我最近才带来了serial设备到开发计算机上,因为我懒散了,厌倦了来回走动。谢谢你指出这一点。我没有考虑到我只是看到了一个问题,因为VS正在运行。@eatumup:不要认为如果没有出现错误,问题就不存在。当你尝试更新时,仍然有一个并发错误潜伏着GUI来自错误的线程。@Tudor,你知道为什么bug在发布模式下不出现吗?你肯定是对的,只是好奇为什么它在发布和调试中表现得很好。@Grant H:我想这是因为发布更注重效率,所以他们可能想避免抛出另一个异常(这很耗时)和冻结应用程序。不幸的是,如果你不是很有经验,结果会更加混乱。我看到许多人简单地认为调试器是问题所在。:)从msdn文档中可以看出:.NET Framework可以帮助你检测何时以非线程安全的方式访问控件。何时运行应用程序在调试器中,如果创建控件的线程以外的线程尝试调用该控件,调试器将引发InvalidOperationException,并显示消息“control control name Access from thread,而非创建该控件的线程”。“此异常在调试期间以及在某些情况下在运行时可靠地发生。强烈建议您在看到此问题时解决此问题。我认为这对我的理解有所帮助。但是,当我添加您的代码段时,错误检查器不喜欢“=>”格式。所以我还是有点困惑。我也搞砸了。rx.text=“”;应该被移除。这是反复试验的结果。@eatumup:您使用的是哪个版本的.net?我的应用程序是为目标framework 4设置的。它也是VisualStudio下的WinForm2010@eatumup:对不起。我漏掉了几个括号。现在应该可以编译了,谢谢你。说实话,我觉得自己很傻。我早该抓到的。但是你的权利。它使它工作得很好。我想我大概有75%了解了BeginInvoke函数的布局逻辑。我只需要多花点时间仔细看看。我也喜欢它的简洁。再次感谢。
    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);
    }