我正在编写一个Windows服务,用于与串行磁条阅读器和中继板(访问控制系统)进行通信。
在另一个程序通过打开与我的服务相同的串行端口“中断”了进程之后,我遇到了代码停止工作的问题(我得到了IOExceptions)。
代码的一部分如下:
public partial class Service : ServiceBase
{
Thread threadDoorOpener;
public Service()
{
threadDoorOpener = new Thread(DoorOpener);
}
public void DoorOpener()
{
while (true)
{
SerialPort serialPort = new SerialPort();
Thread.Sleep(1000);
string[] ports = SerialPort.GetPortNames();
serialPort.PortName = "COM1";
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.Parity = Parity.None;
if (serialPort.IsOpen) serialPort.Close();
serialPort.Open();
serialPort.DtrEnable = true;
Thread.Sleep(1000);
serialPort.Close();
}
}
public void DoStart()
{
threadDoorOpener.Start();
}
public void DoStop()
{
threadDoorOpener.Abort();
}
protected override void OnStart(string[] args)
{
DoStart();
}
protected override void OnStop()
{
DoStop();
}
}我的示例程序成功地启动了工作线程,DTR的打开/关闭和提升导致我的Mag-stripe阅读器启动(等待1秒)、关闭(等待1秒)等等。
如果我启动HyperTerminal并连接到相同的COM端口,HyperTerminal会告诉我该端口当前正在使用中。如果我在HyperTerminal中反复按ENTER键来尝试重新打开端口,那么在几次重试之后将会成功。
这会在我的工作线程中产生IOExceptions,这是意料之中的。然而,即使我关闭了HyperTerminal,我仍然在我的工作线程中得到相同的IOException。唯一的解决办法就是重新启动电脑。
其他程序(不使用.NET库进行端口访问)在这一点上似乎工作正常。
你知道这是什么原因造成的吗?
发布于 2010-07-05 09:32:39
@thomask
是的,超级终端实际上在SetCommState的DCB中启用了fAbortOnError,这解释了SerialPort对象抛出的大部分IOExceptions。一些PC/手持设备也有UART,默认情况下会打开abort on error标志-所以必须让串行端口的初始化例程清除它(微软忽略了这一点)。我最近写了一篇很长的文章来更详细地解释这一点(如果你感兴趣,请参阅this )。
发布于 2009-01-14 01:33:25
你不能关闭别人到端口的连接,下面的代码永远不会工作:
if (serialPort.IsOpen) serialPort.Close();因为你的对象没有打开端口,所以你不能关闭它。
此外,即使在发生异常之后,也应该关闭并处理串行端口。
try
{
//do serial port stuff
}
finally
{
if(serialPort != null)
{
if(serialPort.IsOpen)
{
serialPort.Close();
}
serialPort.Dispose();
}
}如果您希望该进程是可中断的,那么您应该检查端口是否打开,然后关闭一段时间,然后重试,例如。
while(serialPort.IsOpen)
{
Thread.Sleep(200);
}发布于 2009-01-14 01:50:18
您是否尝试过在应用程序中保持端口打开,只需打开/关闭DtrEnable,然后在应用程序关闭时关闭端口?即:
using (SerialPort serialPort = new SerialPort("COM1", 9600))
{
serialPort.Open();
while (true)
{
Thread.Sleep(1000);
serialPort.DtrEnable = true;
Thread.Sleep(1000);
serialPort.DtrEnable = false;
}
serialPort.Close();
}我不熟悉DTR语义,所以我不知道这是否可行。
https://stackoverflow.com/questions/441559
复制相似问题