【问题标题】:C# "using" SerialPort transmit with data lossC#“使用”SerialPort 传输数据丢失
【发布时间】:2012-07-18 04:33:01
【问题描述】:

我是这个论坛的新手,有一个问题困扰了我一段时间。 我的设置是使用 USB/uart 转换器连接到我的电脑的串行字符显示器。我正在以 C++ 样式在单独的写入缓冲区线程中通过 serialPort 类将字节传输到显示器:

private void transmitThread(){
    while(threadAlive){
        if(q.Count > 0){ // Queue not empty
            byte[] b = q.Dequeue();
            s.Write(b,0,b.Length);
            System.Threading.Thread.Sleep(100);
        }
        else{ // Queue empty
            System.Threading.Thread.Sleep(10);
        }
    }
}

假设串行端口已经打开,这可以完美运行并将所有数据传输到显示器。虽然在这个 sn-p 中根本没有异常处理。因此,我正在研究实现一个典型的 C# 功能,即“使用”语句,并且只在需要时打开端口,如下所示:

private void transmitThread(){
    while(threadAlive){
        if(q.Count > 0){ // Queue not empty
            byte[] b = q.Dequeue();
            using(s){ //using the serialPort
                s.Open();
                s.Write(b,0,b.Length);
                s.Close();
            }
            System.Threading.Thread.Sleep(100);
        }
        else{ // Queue empty
            System.Threading.Thread.Sleep(10);
        }
    }
}

这个函数的问题在于,它只传输随机数量的数据,通常约为 80 字节字节数组的三分之一。我尝试了线程的不同优先级设置,但没有任何改变。

我是否遗漏了一些重要的东西,或者我只是在发送请求后关闭端口太快了?

我希望你能帮助我。谢谢:)

【问题讨论】:

  • 那些Sleep() 调用会扼杀你的吞吐量。有没有可以在串行端口对象上调用的 Flush() 方法?
  • 如果使用 using 块,则不需要关闭...
  • @RobertHarvey Dispose 或 Close 将刷新流。
  • 是的,我知道 Sleep(100) 的时间很长,但在接收到 SpecialFunctionCommandBytes 后,显示器似乎需要一些时间。对于字符串输入,它并不关心,但现在我不管它睡着了。

标签: c# serial-port using data-loss


【解决方案1】:

不,那是一个非常糟糕的主意。出错的地方,大致按照你遇到的顺序:

  • 当您关闭端口时,串行端口驱动程序会丢弃发送缓冲区中尚未发送的任何字节。这就是你现在看到的。

  • SerialPort.Close() 的 MSDN 文章警告您必须“等待一段时间”才能再次打开端口。有一个内部工作线程需要关闭。您必须等待的时间量未指定,并且是可变的,具体取决于机器负载。

  • 关闭端口允许另一个程序获取并打开端口。串口无法共享,再次打开程序会失败。

串行端口的设计根本不是为了即时打开和关闭。只在程序开始时打开它,结束时关闭它。完全不调用 Close() 是完全可以接受的,并且可以避免死锁情况。

【讨论】:

  • 所以基本上你建议我不要使用'using'语句,并保留我的原始设计?然后我需要添加一个 try-catch。
【解决方案2】:

我认为您错过了 using 块的要点。典型的 using 块如下所示:

using (var resource = new SomeResource())
{
    resource.DoSomething();
}

开头发生在最开始。通常作为构造函数的一部分。但有时在 using 块的第一行。

但我看到的大红旗是关闭自动发生。你不需要.Close() 电话。

【讨论】:

    【解决方案3】:

    如果您的串行设备的成功操作依赖于对Thread.Sleep 的调用,那么线程可能在某个时候被中断,足以使数据传输与设备不同步。很可能有办法解决这个问题,但我要做的第一件事是尝试使用 .NET SerialPort 类。 Write 方法和你想做的很相似,那些文章里有C++代码示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      相关资源
      最近更新 更多