有时我的某些集成测试会因上述消息而失败.我正在使用下面的代码来准备端口.
for(int i = 0; i < 5; i++)
{
try
{
port.Open();
if (port.IsOpen)
break;
}
catch (Exception e)
{
try
{
port.Close();
}
catch (Exception)
{}
Thread.Sleep(300);
}
}
Run Code Online (Sandbox Code Playgroud)
我的假设是,因为它不能阻止端口的当前线程(因为它会尝试关闭它),它必须是另一个线程或进程已经死亡而没有正确清理(其他测试之一 - 没有其他访问这个港口).有没有办法重置状态,SerialPort以便新线程/进程可以再次访问它?
谢谢,
理查德
Han*_*ant 16
这是SerialPort类中的一个缺陷,它使用内部帮助程序线程来等待端口上的事件.DataReceived,PinChanged和ErrorReceived事件的来源.该缺陷在Close()方法实现中,它不等待这个辅助线程终止.这需要时间,确切的时间量是不可预测的,并且当机器特别繁忙时可能需要很多秒.在发生这种情况之前,物理端口不会关闭,在线程退出炸弹之前打开端口并使用"已在使用的端口"例外.你得到的那个.因此,睡眠300毫秒是不够的.
这通常不是问题,串口不是可共享的设备.关闭串口而不退出程序是危险的,另一个进程可能会窃取端口.当您尝试再次打开它时也会给您这个例外.通常的做法是在应用程序启动时打开端口,而不是关闭它直到它终止.
我通常在实例化串行端口之前先验证端口是否已关闭。如果您在不关闭串行端口的情况下停止调试代码,则将有帮助。另外,在打开或关闭端口之后,您应该等待250毫秒,然后再继续执行代码。
try
{
if ((m_SerialPort != null))
{
if (m_SerialPort.IsOpen)
{
m_SerialPort.Close();
}
}
m_SerialPort = new SerialPort(portName, dataRate, parity, databits, stopBits.One);
m_SerialPort.Open();
if (!m_SerialPort.IsOpen)
{
MessageBox.Show(string.Concat(portName, " failed to open"));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Run Code Online (Sandbox Code Playgroud)