串行端口和 ObjectDisposeException 安全句柄已关闭

发布于 2024-08-16 06:39:20 字数 2208 浏览 3 评论 0原文

我正在从通过串行端口发送信息的设备接收数据,但收到此异常:“ObjectDisposeException 安全句柄已关闭”。它可能会在几秒钟到几分钟内发生,而且似乎没有任何模式。发生的另一件事是,它将无一例外地停止接收数据,并且我可以在 VS IDE 输出窗口选项卡中看到线程已退出。我不知道为什么它也这样做。

这是我创建串行端口的方法:

DeviceSerialPort serialport = new DeviceSerialPort("COM1", 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);
serialport.RHDataReceived += new EventHandler<DeviceDataEventArgs>(SerialPort_RHDataReceived);
serialport.Open();

这是串行端口代码:

namespace Instrument
{
    public class DeviceSerialPort
    {
        public event EventHandler<DeviceDataEventArgs> RHDataReceived;

        private SerialPort _serialPort;
        private byte[] _readBuffer = new byte[1024];

        public DeviceSerialPort(string portName, int baudRate, Parity parity, 
            int dataBits, StopBits stopBits)
        {
            _serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
            _serialPort.DataReceived +=new SerialDataReceivedEventHandler(SerialPort_DataReceived);

        }

        public void Open()
        {
            _serialPort.Open();
        }

        private void SerialPort_DataReceived(object sender, EventArgs e)
        {
            //SerialPort sp = (SerialPort)sender;

            int bytesRead = _serialPort.Read(_readBuffer, 0, _readBuffer.Length);


            if (_readBuffer[0] == 5)
            {
                onRHDataReceivedEvent(new DeviceDataEventArgs(_readBuffer[0], _readBuffer[1], _readBuffer[2], _readBuffer[3]));
            }
        }


        protected void onRHDataReceivedEvent(DeviceDataEventArgs e)
        {
            if (RHDataReceived != null)
            {
                RHDataReceived(this, e);
            }
        }

    }

    public class DeviceDataEventArgs : EventArgs
    {
        public byte Command { get; set; }
        public byte Data0 { get; set; }
        public byte Data1 { get; set; }
        public byte Crc { get; set; }

        public DeviceDataEventArgs(byte cmd, byte data0, byte data1, byte crc)
        {
            Command = cmd;
            Data0 = data0;
            Data1 = data1;
            Crc = crc;
        }
    }
}

I am receiving data from a device that's sending information over the serial port and I get this exception: "ObjectDisposedException Safe Handle has been closed". It may happen within seconds to several minutes and there doesn't seem to be a pattern. Another thing that happens is that it will stop receiving data with no exception and I can see in the VS IDE output window tab that a thread has exited. I have no idea why it's doing that also.

Here is how I create the serial port:

DeviceSerialPort serialport = new DeviceSerialPort("COM1", 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);
serialport.RHDataReceived += new EventHandler<DeviceDataEventArgs>(SerialPort_RHDataReceived);
serialport.Open();

And here is the serial port code:

namespace Instrument
{
    public class DeviceSerialPort
    {
        public event EventHandler<DeviceDataEventArgs> RHDataReceived;

        private SerialPort _serialPort;
        private byte[] _readBuffer = new byte[1024];

        public DeviceSerialPort(string portName, int baudRate, Parity parity, 
            int dataBits, StopBits stopBits)
        {
            _serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
            _serialPort.DataReceived +=new SerialDataReceivedEventHandler(SerialPort_DataReceived);

        }

        public void Open()
        {
            _serialPort.Open();
        }

        private void SerialPort_DataReceived(object sender, EventArgs e)
        {
            //SerialPort sp = (SerialPort)sender;

            int bytesRead = _serialPort.Read(_readBuffer, 0, _readBuffer.Length);


            if (_readBuffer[0] == 5)
            {
                onRHDataReceivedEvent(new DeviceDataEventArgs(_readBuffer[0], _readBuffer[1], _readBuffer[2], _readBuffer[3]));
            }
        }


        protected void onRHDataReceivedEvent(DeviceDataEventArgs e)
        {
            if (RHDataReceived != null)
            {
                RHDataReceived(this, e);
            }
        }

    }

    public class DeviceDataEventArgs : EventArgs
    {
        public byte Command { get; set; }
        public byte Data0 { get; set; }
        public byte Data1 { get; set; }
        public byte Crc { get; set; }

        public DeviceDataEventArgs(byte cmd, byte data0, byte data1, byte crc)
        {
            Command = cmd;
            Data0 = data0;
            Data1 = data1;
            Crc = crc;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瞄了个咪的 2024-08-23 06:39:20

您的线程的寿命非常短,它的寿命恰好是打开串行端口所需的时间,然后结束。当它发生时,你的串行端口就会被处理掉。

我是这样看的。您使用的是基于事件的方法(处理 DataReceived 事件),在这种情况下,您不需要另一个线程,这在框架和操作系统资源方面是昂贵的。在您的情况下,只需删除 Thread 对象,然后直接调用 serialPort.Open() 即可。您将在现有线程中收到 DataReceived 事件。

Your thread is very short lived, it lives for exactly the length of time it takes to open the serial port, and then it finishes. And when it does, your serial port gets disposed.

This is how I see it. You're using an event-based approach (handling the DataReceived event), in which case, you don't need another thread, which is expensive in terms of framework and OS resources. In your case, simply get rid of the Thread object, and call serialPort.Open() directly. You will receive the DataReceived events in your existing thread.

宣告ˉ结束 2024-08-23 06:39:20

使用以下方法在 form_load 中注册未处理的异常处理程序:

AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledException_Handler

并添加处理程序:

'This sub does the magic
Private Sub UnhandledException_Handler(ByVal sender As Object, ByVal args As UnhandledExceptionEventArgs)
    Dim ex As Exception = DirectCast(args.ExceptionObject, Exception)
    Thread.CurrentThread.Suspend()
End Sub

Register the unhandled exception handler in form_load using:

AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledException_Handler

And add the handler:

'This sub does the magic
Private Sub UnhandledException_Handler(ByVal sender As Object, ByVal args As UnhandledExceptionEventArgs)
    Dim ex As Exception = DirectCast(args.ExceptionObject, Exception)
    Thread.CurrentThread.Suspend()
End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文