C# SerialPort 的“已关闭SafeHandle”

C# SerialPort 的“已关闭SafeHandle”

最近在做一个项目,其中有一个部分就是通过USB口转串口,和别人的设备通讯。所以,就要做一个可以自动搜索设备的功能。基本的想法是我先获取所有的端口名,然后再去验证这些端口是不是有设备的那个端口。验证的方法就是先给端口写一些数据,然后再去读这个口,看数据是否有我想要的标志,有的话就是有设备的口。 
 然后我写了一段程序,感觉没问题,但是运行的时候就会提示“已关闭SafeHandle”,我把代码贴出来(第一段)。我们可以看到我写的一个局部变量 p(SerialPort),每次读写数据完我都会关闭它。网上查了很多资料,说“已关闭SafeHandle”这个错误是因为我的串口还在读写数据,但是资源被释放,所以报错。我反复想来想去,接近崩溃。 
 后来师兄建议我用SerialPort组件去试试,所以我试了,见第二段代码。当循环运行到“myPort.PortName = portname;”这句时它居然提示我“端口打开时不能更改PortName”,我就觉得很郁闷,因为这个组件我读写完就关闭了。然后我就在更改PortName前加了一个强制关闭串口的代码,它居然就可以了!所以,我想之前那段程序的问题应该是:我表面上虽然已经关闭了局部创建的串口p,但实际上没有关闭,close()方法可能存在某些问题。
 所以,我把第一段的程序中的P改为全局变量,不然判断isOpen的时候没有实例,然后加了几句判断是否关闭的代码,结果果然问题解决!见第三段代码。

第一段代码

public class ExpandIO
{
    public List<IODevice> Devices = new List<IODevice>();
    public void Detect()
    {
        try
        {
            SerialPort.GetPortNames();
            foreach (string portname in SerialPort.GetPortNames())
            {
                if (!Devices.Exists(x => x.PortName == portname))
                {
                    try
                    {
                        char[] b = { ':', 'D', 'T', 'C', 'T' };
                        SerialPort p = new SerialPort(portname, 115200, Parity.None, 8, StopBits.One);
                        p.ReadTimeout = 1000;
                        p.WriteTimeout = 1000;
                        if (!p.IsOpen)
                        {
                            p.Open();
                            Thread.Sleep(100);
                            p.Write(b, 0, 5);
                            Thread.Sleep(100);
                            p.Read(b, 0, 5);
                            p.Close();
                            Thread.Sleep(100);
                            if (b[0] == 'O' && b[1] == 'K')
                            {
                                IODevice d = new IODevice
                                 {
                                     PortName = portname,
                                     id = (byte)b[2]
                                 };
                                Devices.Add(d);
                            }
                        }
                    }
                    catch { }
                }
            }
        }
        catch { }
        foreach (IODevice dev in Devices)
        {
            dev.start();
        }

第二段代码

// TODO: 查找输出设备
    void Detect()
    {
        try
        {
            foreach (string portname in SerialPort.GetPortNames())
            {
                if (!myDevices.Exists(x => x.PortName == portname))
                {
                    try
                    {
                        char[] b = { ':', 'D', 'T', 'C', 'T' };
                          // 注释的这部分是后来加的
                        //while (myPort.IsOpen)
                        //{
                        //    myPort.Close();
                        //}
                        myPort.PortName = portname;
                        if (!myPort.IsOpen)
                        {
                            myPort.Open();
                            myPort.DiscardInBuffer();
                            myPort.DiscardOutBuffer();
                            Thread.Sleep(100);
                            myPort.Write(b, 0, 5);
                            Thread.Sleep(100);
                            myPort.Read(b, 0, 5);
                            myPort.Close();
                            Thread.Sleep(100);
                            if (b[0] == 'O' && b[1] == 'K')
                            {
                                IODevice d = new IODevice
                                {
                                    PortName = portname,
                                    id = (byte)b[2]
                                };
                                myDevices.Add(d);
                            }
                        }
                    }
                    catch { }
                }
            }
        }
        catch { }
    }

第三段代码

 public class ExpandIO
{
    public List<IODevice> Devices = new List<IODevice>();
    SerialPort p = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
    public void Detect()
    {
        try
        {
            foreach (string portname in SerialPort.GetPortNames())
            {
                if (!Devices.Exists(x => x.PortName == portname))
                {
                    try
                    {
                        char[] b = { ':', 'D', 'T', 'C', 'T' };
                        while (p.IsOpen)
                        {
                            p.Close();
                        }
                        p = new SerialPort(portname, 115200, Parity.None, 8, StopBits.One);
                        p.ReadTimeout = 1000;
                        p.WriteTimeout = 1000;
                        if (!p.IsOpen)
                        {
                            p.Open();
                            Thread.Sleep(100);
                            p.Write(b, 0, 5);
                            Thread.Sleep(100);
                            p.Read(b, 0, 5);
                            p.Close();
                            Thread.Sleep(100);
                            if (b[0] == 'O' && b[1] == 'K')
                            {
                                IODevice d = new IODevice
                                {
                                    PortName = portname,
                                    id = (byte)b[2]
                                };
                                Devices.Add(d);
                            }
                        }
                    }
                    catch { }
                }
            }
            foreach (IODevice dev in Devices)
            {
                dev.start();
            }
        }
        catch { }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值