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