首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用.NET / C#进行健壮的SerialPort编程?

如何使用.NET / C#进行健壮的SerialPort编程?
EN

Stack Overflow用户
提问于 2009-01-14 01:19:03
回答 9查看 55.8K关注 0票数 26

我正在编写一个Windows服务,用于与串行磁条阅读器和中继板(访问控制系统)进行通信。

在另一个程序通过打开与我的服务相同的串行端口“中断”了进程之后,我遇到了代码停止工作的问题(我得到了IOExceptions)。

代码的一部分如下:

代码语言:javascript
复制
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库进行端口访问)在这一点上似乎工作正常。

你知道这是什么原因造成的吗?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2010-07-05 09:32:39

@thomask

是的,超级终端实际上在SetCommState的DCB中启用了fAbortOnError,这解释了SerialPort对象抛出的大部分IOExceptions。一些PC/手持设备也有UART,默认情况下会打开abort on error标志-所以必须让串行端口的初始化例程清除它(微软忽略了这一点)。我最近写了一篇很长的文章来更详细地解释这一点(如果你感兴趣,请参阅this )。

票数 24
EN

Stack Overflow用户

发布于 2009-01-14 01:33:25

你不能关闭别人到端口的连接,下面的代码永远不会工作:

代码语言:javascript
复制
if (serialPort.IsOpen) serialPort.Close();

因为你的对象没有打开端口,所以你不能关闭它。

此外,即使在发生异常之后,也应该关闭并处理串行端口。

代码语言:javascript
复制
try
{
   //do serial port stuff
}
finally
{
   if(serialPort != null)
   {
      if(serialPort.IsOpen)
      {
         serialPort.Close();
      }
      serialPort.Dispose();
   }
}

如果您希望该进程是可中断的,那么您应该检查端口是否打开,然后关闭一段时间,然后重试,例如。

代码语言:javascript
复制
while(serialPort.IsOpen)
{
   Thread.Sleep(200);
}
票数 4
EN

Stack Overflow用户

发布于 2009-01-14 01:50:18

您是否尝试过在应用程序中保持端口打开,只需打开/关闭DtrEnable,然后在应用程序关闭时关闭端口?即:

代码语言:javascript
复制
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语义,所以我不知道这是否可行。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/441559

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档