如何使用 .NET/C# 进行健壮的 SerialPort 编程? [英] How to do robust SerialPort programming with .NET / C#?

查看:18
本文介绍了如何使用 .NET/C# 进行健壮的 SerialPort 编程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a Windows Service for communication with a Serial Mag-stripe reader and a relay board (access control system).

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

I run into problems where the code stops working (i get IOExceptions) after another program has "interrupted" the process by opening the same serial port as my service.

部分代码如下:

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 的打开/关闭和提升导致我的磁条阅读器通电(等待 1 秒)、关闭(等待 1 秒)等等.

My sample program successfully starts the work-thread, and the opening/closing and raising of DTR causes my Mag-stripe reader to power up (wait 1sec), shut down (wait 1 sec) and so on.

如果我启动超级终端并连接到同一个 COM 端口,超级终端会告诉我该端口当前正在使用中.如果我在超级终端中反复按 ENTER,尝试重新打开重试几次后会成功的端口.

If I launch HyperTerminal and connects to the same COM port, HyperTerminal tells me the port is currently in use. If i repeatedly press ENTER in HyperTerminal, to try to reopen the port it will succeed after a few retries.

这会在我的工作线程中导致 IOExceptions,这是预期的.但是,即使我关闭了超级终端,我的工作线程中仍然会收到相同的 IOException.唯一的治疗方法实际上是重新启动计算机.

This has the effect of causing IOExceptions in my work-thread, which is expected. However, even if I close down HyperTerminal, i still get the same IOException in my work-thread. The only cure is actually to restart the computer.

其他程序(未使用 .NET 库进行端口访问)此时似乎可以正常工作.

Other programs (which is not using .NET libraries for port-access) seem to work normally at this point.

关于造成这种情况的任何想法?

Any ideas as to what is causing this?

推荐答案

@thomask

是的,Hyperterminal 实际上在 SetCommState 的 DCB 中启用了 fAbortOnError,这解释了 SerialPort 对象抛出的大多数 IOExceptions.一些 PC/手持设备还具有默认打开错误中止标志的 UART - 因此串行端口的 init 例程必须清除它(微软忽略了这样做).我最近写了一篇长文来更详细地解释这一点(参见 this 如果你有兴趣).

Yes, Hyperterminal does in fact enable fAbortOnError in SetCommState's DCB, which explains for most of the IOExceptions thrown by the SerialPort object. Some PCs / handhelds also have UARTs that have the abort on error flag turned on by default - so it's imperative that a serial port's init routine clears it (which Microsoft neglected to do). I wrote a long article recently to explain this in greater detail (see this if you're interested).

这篇关于如何使用 .NET/C# 进行健壮的 SerialPort 编程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆