【问题标题】:Serial Comms C#串行通信 C#
【发布时间】:2013-01-03 03:34:51
【问题描述】:

我正在编写一个 C# 应用程序以通过串行与微控制器进行通信。我有几个关于如何处理收到的消息的问题。下面是我目前使用的代码,它接收到的消息非常好,但我无法更新表单,或将数据存储在此方法之外的任何地方(因为它位于另一个线程中)。

com.DataReceived += new SerialDataReceivedEventHandler(OnReceived);


public void OnReceived(object sender, SerialDataReceivedEventArgs c) // This is started in another thread...
    {
        com.DiscardOutBuffer();
        try
        {
            test = com.ReadExisting();
            MessageBox.Show(test);       
        }
        catch (Exception exc) 
        {
            MessageBox.Show(exc.ToString());
        }
    }

当我尝试更改表单或从此处调用其他方法时,我收到以下错误消息:“Cross Thead 操作无效”。

我希望能够在其他地方显示信息,或者甚至更好地将其放入数组中,以便以后存储为文件。有什么办法可以做到吗?

再次感谢!

【问题讨论】:

    标签: c# oop serial-port


    【解决方案1】:

    您需要使用InvokeBeginInvoke 在主线程上调用:

    public void OnReceived(object sender, SerialDataReceivedEventArgs c)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(OnReceived), sender, c);
            return;
        }
    
        com.DiscardOutBuffer();
        try
        {
            test = com.ReadExisting();
            MessageBox.Show(test);       
        }
        catch (Exception exc) 
        {
            MessageBox.Show(exc.ToString());
        }
    }
    

    或者您可以提取事件处理程序的一部分(例如显示消息框)并调用它。

    【讨论】:

    • 效果很好,谢谢!调用完成了什么?
    • @VRKnight 它告诉主(GUI)线程执行您的代码,而不是后台线程。只有 GUI 线程被允许修改 GUI(比如显示一个消息框),所以这是必要的。
    【解决方案2】:

    您遇到的问题是您尝试从非 UI 线程更新 UI。您需要做的是在 UI 线程上调用 MessageBox

    类似:

    public void OnReceived(object sender, SerialDataReceivedEventArgs c) // This is started in another thread...
    {
        com.DiscardOutBuffer();
        try
        {
            test = com.ReadExisting();
            SetValue(test);       
        }
        catch (Exception exc) 
        {
            SetValue(exc.ToString());
        }
    }
    
    
    delegate void valueDelegate(string value);
    
    private void SetValue(string value)
    {   
        if (this.InvokeRequired)
        {
            this.Invoke(new valueDelegate(SetValue),value);
        }
        else
        {
            MessageBox.Show(value);
        }
    }
    

    【讨论】:

    • 这两个答案都有效,Invoke 到底是什么意思?
    • 这里有一点阅读,但基本上,它意味着在UI控件拥有或所属的线程上执行请求的代码。从技术上讲,您可以在不调用(通过禁用调试器设置)的情况下做您想做的事情,但它是不安全的,因此调用确保跨线程正确执行。 msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多