繁体   English   中英

在富文本框中显示串行端口数据期间“无法访问已处理的对象”

[英]"Can't access a Disposed object" during Serial Port Data being displayed in Rich text Box

我正在尝试使用 C# 制作串行数据绘图仪。 我有一个 Arduino 作为串行数据流设备,它不断地向 PC 发送数据。 我的应用程序应该接收该数据并将其显示在富文本框中。 进一步的应用非常复杂,但这是基本的构建块。

现在,如果数据速率很慢,数据会被正确接收。 我可以使用提供的按钮连接和断开串行端口。

当数据速率很快时就会出现问题。 在数据接收期间,如果我尝试断开连接,则会引发“无法访问已处理对象”的错误。 我发布相同的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO.Ports;
using System.Windows.Forms;

namespace Serial_Port_reference
{
    public partial class Form1 : Form
    {
        bool cnctBtn_state = false;

        public SerialPort sp = new SerialPort();
        string[] portNames;

        delegate void SetTextCallback(string text);
        delegate void SetIntCallback(int value);

        bool spClosesd = false;

        private void SetoutputRtb(string text)
        {
            if (outputRtb.InvokeRequired)
            {

                SetTextCallback d = new SetTextCallback(SetoutputRtb);
                Invoke(d, new object[] { text });
            }
            else
            {
                outputRtb.AppendText(text);
                outputRtb.ScrollToCaret();
            }
        }

        public Form1()
        {
            InitializeComponent();
        }

        //Serial Port Receive Interrupt
        public void serialReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string temp = null;
            try
            {
                temp = sp.ReadTo("#");
                SetoutputRtb(temp);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.ToString());
            }


        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cnctBtn.BackColor = Color.ForestGreen;
            cnctBtn.ForeColor = Color.White;

            sp.DataReceived += new SerialDataReceivedEventHandler(serialReceived);
            portNames = SerialPort.GetPortNames();

            foreach (string ports in portNames)
            {
                portCombo.Items.Add(ports);
            }

            portCombo.SelectedIndex = 0;



        }

        private void cnctBtn_Click(object sender, EventArgs e)
        {
            if (cnctBtn_state == false)
            {
                sp.PortName = portCombo.SelectedItem.ToString();
                sp.BaudRate = int.Parse(baudCombo.SelectedItem.ToString());
                sp.DataBits = 8;
                sp.StopBits = StopBits.One;
                sp.Parity = Parity.None;

                try
                {
                    sp.Open();
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.ToString());
                    return;
                }

                cnctBtn.Text = "Disconnect";
                cnctBtn.BackColor = Color.PaleVioletRed;

                cnctBtn_state = true;
            }
            else
            {
                try
                {
                    //Thread.Sleep(1000);
                    sp.DiscardInBuffer();

                    //sp.Dispose();
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.ToString());
                    return;
                }

                cnctBtn.Text = "Connect";
                cnctBtn.BackColor = Color.LightCoral;

                cnctBtn_state = false;
            }
        }

        private void sendTxtButton_Click(object sender, EventArgs e)
        {
            try
            {
                sp.Write(sendTxtBox.Text);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.ToString());
            }

            sendTxtBox.Clear();
        }
    }
}

我使用 Invoke 方法进行跨线程调用以在 RTB 中写入,这就是程序停止的地方。

根据我的理解,我尝试了很多不同的事情以及在不同论坛上给出的建议,但没有一个与串行端口特别相关,因此我无法实现它们。 我了解问题的性质,但不知道如何实现安全方法来捕获 ObjectDisposeExceptions 或主要防止它们。 我是 C# 编程的新手,因此可能需要对编程部分进行更多解释。 提前致谢!

我假设您通过 sp.Dispose() 关闭连接? 它目前已在您的代码中注释掉。 通常你会想要使用 Close() - 它会丢弃输入和输出缓冲区。

但我认为您可能正在接收数据并且 DataReceived 事件正在触发但不一定在您执行 Dispose 时交付。 交付时,您的 sp 串行端口已被处理,因此我怀疑您的 serialReceived() 函数中的 sp.ReadTo() 出现错误。 事实上,仔细观察,当(如果)您执行 Close() 时,您将获得另一个事件——“文件结束”指示将导致 DataReceived 事件。

您可以在处理后设置 sp = null,然后在读取之前在 serialReceived() 函数中检查它。 无论如何,这是一个很好的做法。 您可能知道,DataReceived 事件将在不同的线程中运行 serialReceived。 我不确定是否可以在 Dispose() 调用和 sp=null 之间安排它。

所以,我认为最好的办法是在调用 Close() 之前断开事件:

sp.DataReceived += serialReceived.

另一件事——我以前没有使用过 ReadTo(),但它似乎会阻塞,直到收到该字符。 这是你所期望的吗? 如果一个字符进来,您的事件将触发,但该线程将阻塞,直到收到“#”。 我认为更典型的 DataReceived 事件处理程序会读取和处理所有可用字节,并将其解析出来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM