我正在开发一个从托盘运行的C#WinForms Windows应用程序.我需要为用户提供一些合理的错误处理和指令.为了测试我是否能够打开串行端口进行通信,我希望有一种方法来测试它是否已经打开或者由于某种原因它是不可打开的.
我想出了这个:
if (SerialPort.GetPortNames().Select((n) =>
n.ToUpperInvariant()).Contains(mycomportname))
{
// Port found, check to see if we can use it by test-opening
using (var sp = new SerialPort(mycomportname))
{
// Check to see if we can open this port
try
{
if (sp.IsOpen) throw new Exception("Serial port is already open");
sp.Open();
sp.Close();
}
catch (Exception ex)
{
throw new Exception("Serial port is in use");
}
}
}
else
{
// ...
}
commManager.PortName = mycomportname;
if (commManager.OpenPort())
{
// .. always returns false because causes UnauthorizedAccessException on open
}
Run Code Online (Sandbox Code Playgroud)
由于某种原因,'using'语句似乎没有完全释放串口.当我删除using语句及其中的语句时,不会发生UnauthorizedAccessException.如何编写可靠的容错串行端口打开代码?
虽然含糊不清,但有关SerialPort的MSDN文章明确警告了这一点.SerialPort使用工作线程生成DataReceived和ErrorReceived等事件.调用Open()时该线程启动但在调用Close()或Dispose()后需要时间再次退出.物理端口正在使用,直到发生这种情况.究竟需要多长时间才是不可预测的.通常在一毫秒内,但最坏的情况是机器负载很重的几秒钟.您的代码只等待一个纳秒,因此您将始终获得异常.
否则这种方法没有意义.一旦你打开端口并且没有例外,那就让它保持打开状态.没有必要再次关闭它并重新打开它.哪个是简单的解决方案.
当GetPortNames()返回多个端口时,永远不要进行这种端口扫描.第一个开的几率非常高,正确的几率很低.墨菲确保五十五赔率变为1%.您始终需要提供配置文件,以便用户可以选择正确的配置文件.在配置帮助程序窗口中使用选项填充组合框时,只考虑进行端口扫描.如果您能控制机器配置,那么只能吝啬这一点,这种情况非常罕见.