[英]"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.