Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关闭USB串行端口会使端口不可用_C#_Wpf_.net 4.0 - Fatal编程技术网

C# 关闭USB串行端口会使端口不可用

C# 关闭USB串行端口会使端口不可用,c#,wpf,.net-4.0,C#,Wpf,.net 4.0,我的应用程序使用基于USB的串行端口连接到物理硬件设备。我可以打开任何有效的USB端口并与外部设备通信。但是,当我关闭连接时,USB端口在一段时间内处于某种不确定状态,在此期间,进一步尝试重新连接会导致“访问端口”COM--“被拒绝”错误。但是,几秒钟后,尝试重新连接成功。如何确定USB端口何时再次支持新连接 代码如下所示: private void Setup(string Port) { bool ValidPort = false; int

我的应用程序使用基于USB的串行端口连接到物理硬件设备。我可以打开任何有效的USB端口并与外部设备通信。但是,当我关闭连接时,USB端口在一段时间内处于某种不确定状态,在此期间,进一步尝试重新连接会导致“访问端口”COM--“被拒绝”错误。但是,几秒钟后,尝试重新连接成功。如何确定USB端口何时再次支持新连接

代码如下所示:

    private void Setup(string Port)
    {
        bool ValidPort = false;
        int CloseSleep = 10;

        _PortName = Port;
        _PortType = this;

        string[] AvailablePorts = SerialPort.GetPortNames();  

        foreach(string aPort in AvailablePorts)
        {
            if (aPort == _PortName)
            {
                // The required port is listed in the list of available ports)
                ValidPort = true;
                break;
            }
        }

        if (ValidPort)
        {
            try
            {
                if (_ThePort != null)
                {
                    _ThePort.Close();
                    _ThePort.DataReceived -= ReceivedDataEventHandler;

                    while(CloseSleep-- > 0)
                        System.Threading.Thread.Sleep(100);

                    _ThePort.Dispose();
                    _ThePort = null;
                }
            }
            catch (Exception ex)
            {
                EMS_Config_Tool.ModalDialog md = new EMS_Config_Tool.ModalDialog("Closing Port: " + ex.Message, "System Exception");
                md.ShowDialog();
            }

            System.IO.Ports.SerialPort TheNewPort = new System.IO.Ports.SerialPort(Port, 38400);

            // Setup the event handlers from Tx and Rx
            Handler.DataOutEvent    += CommsSender;
            TheNewPort.DataReceived += ReceivedDataEventHandler;

            TheNewPort.DataBits  = 8;
            TheNewPort.Parity    = Parity.None;
            TheNewPort.Handshake = System.IO.Ports.Handshake.None;
            TheNewPort.StopBits  = System.IO.Ports.StopBits.One;

            // We will try 3 times to open the port, and report an error if we fail to open the port
            try
            {
                TheNewPort.Open();
            }
            catch (Exception)
            {
                System.Threading.Thread.Sleep(1000);

                try
                {
                    TheNewPort.Open();
                }
                catch (Exception)
                {
                    System.Threading.Thread.Sleep(1000);

                    try
                    {
                        TheNewPort.Open();
                    }
                    catch (Exception ex)
                    {
                        EMS_Config_Tool.ModalDialog md = new EMS_Config_Tool.ModalDialog("Opening Port: " + ex.Message, "System Exception");

                        return;
                    }
                }
            }

最后一个catch语句是发出拒绝访问错误的地方。请注意,我尝试重试打开端口3次并没有真正的帮助。如果我将端口单独保留大约5到10秒,然后重试调用安装方法,它会立即成功。

正如@Neil所说,存在许多问题。在我看来,最好的办法是将搜索放在一个循环中,一旦端口可以打开,它就会被打开

我以前是这样做的:

public Task WaitingPort()
{
    while (port is null)
        {
            port = CheckPort();
        }
}

private SerialPort CheckPort()
{
    string[] listPort = SerialPort.GetPortNames();
    foreach(string namePort in listPort)
    {
        SerialPort port = new SerialPort(namePort, 9600);
        if (!port.IsOpen)
        {
            try
            {
                port.Open();
                port.ReadTimeout = 1500;
                string data = port.Readline();
                // I programmed my device to send an "A" until it receives
                // "777" to be able to recognize it once opened
                if (data.Substring(0, 1) == "A") 
                {
                    port.ReadTimeout = 200;
                    port.Write("777"); // to make it stop sending "A"
                    return port;
                }
                else
                {
                port.Close();
                }
            }
            catch (Exception e1)
            {
                port.Close();
            }
        }
    }
    return null;
}

当然,这只是一种模板,您必须根据自己的用途对其进行重塑

我已经修改了我的代码,以使用受约束的循环,从而为其提供更好的工作机会,这通常是可以做到的。我希望有更好的方法,因为我倾向于有相当不耐烦的用户,如果他们必须等待5或10秒才能建立连接,他们就会发布缺陷报告

            // We will try several times to open the port, upto 10 times over 5 seconds, and report an error if we finally fail to open the port
            try
            {
                TheNewPort.Open();
            }
            catch (Exception ex)
            {
                RetryOpenTimer.Interval = 500;
                RetryCount = 10;
                RetryOpenTimer.Elapsed += new System.Timers.ElapsedEventHandler(RetryOpenTimer_Elapsed);
                WaitForOpen = true;
                RetryOpenTimer.Start();

                while (WaitForOpen && RetryCount > 0)
                {
                    System.Threading.Thread.Sleep(500);
                }
                if (WaitForOpen)
                {
                    EMS_Config_Tool.ModalDialog md = new EMS_Config_Tool.ModalDialog("Opening Port: " + ex.Message, "System Exception");
                    return;
                }
            }


串行端口驱动程序(特别是USB串行端口)是出了名的坏。除非是昂贵的,否则它可能是基于(坏的)FTTI(?)驱动源的,它有很多问题。如果你能让它工作的唯一方法是在两次使用之间等待5到10秒,那么你可能已经得到了最好的答案。这是FTDI和哦,天哪。为什么要在调用端口.Dispose()之前添加延迟?无论如何,代码需要一点清理。重试可以在一个循环中,而不是嵌套在另一个循环中。我同意“清理”。。。。我尝试的是一个Q&D尝试,看看在处理之前等待结束是否会有帮助(它没有:)…但在我的第一篇帖子之后,我将它修改成了一个更可接受的东西…(也许)我刚从我们的一位硬件工程师那里得知,我们的USB不是基于FTDI的,而是嵌入在RX处理器中,并作为软件任务处理。。。。。我应该快乐吗?不,仍然不能很好地工作…但也许(作为一个软件任务)可以再次查看并“清理”以使其工作得更好。。。。
    void RetryOpenTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        RetryOpenTimer.Stop();
        RetryOpenTimer.Elapsed -= RetryOpenTimer_Elapsed;

        try
        {
            if (RetryCount-- > 0)
            {
                TheNewPort.Open();

                WaitForOpen = false;
            }
            else
                return;
        }
        catch (Exception)
        {
            RetryOpenTimer.Start();
            RetryOpenTimer.Elapsed += RetryOpenTimer_Elapsed;
        }
    }