【问题标题】:C# Receive and transmit serial bytes at the same time bugC#同时接收和发送串行字节的bug
【发布时间】:2017-09-12 08:26:24
【问题描述】:

我正在使用我的应用程序时突然意识到如果我在读取一个字节时传输一个字节,则串行端口可能会出错。我开始测试,在 5 秒内,宾果游戏。我没有错过收到的字节。但是我的程序将停止正常工作。我们使用某种协议,当它接收到奇怪的字节时,它可能会卡住。类似的事情也会发生。

为了发送字节,我使用按钮,按钮事件调用发送字节的函数。

serial.Write(toSend, 0, 1)

为了读入,我使用串行事件调用处理数据的后台工作人员。

private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        lock (_lock)
        {
            rxBuffer += serial.ReadExisting();
        }
             try { backgroundWorker1.RunWorkerAsync(); } catch { } 
    }

控制台输出

Bullseye set at (0,1)
9:44:52  << 0x80
9:44:52  << 0x3
9:44:52  << 0xA
Bullseye set at (1,1)
9:44:52  << 0x80
9:44:52  << 0x3
9:44:52  << 0xB
Bullseye set at (2,1)
9:44:52  << 0x80
9:44:52  0x95 >>
9:44:52  << 0x3
9:44:52  << 0xC   <-- bullseye didn't get set
9:44:53  << 0x80

后台工作人员也使用锁功能。

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            //private void serialReceived(object s, EventArgs e)
            //{     
            while (rxBuffer.Length > 0)
            {
                lock (_lock)
                {
                    // textBox1.Text += rxBuffer[0];
                    byte b = Convert.ToByte(rxBuffer[0]);
                    string hexValue = b.ToString("X");

                    rxBuffer = rxBuffer.Remove(0, 1);

我不知道为什么按钮事件会干扰后台工作人员。我确实看到我收到了所有字节

【问题讨论】:

  • 不过,日志讲述了一个不同的故事。您正在看到 0x3、0xC,所以它已经收到了,不是吗?似乎您用于确定何时“设置靶心”的“触发”功能被发送丢弃了。
  • 您需要发布更多代码来分析问题。考虑创建一个minimal reproducible example
  • 这是非常错误的代码,lock 语句什么也没做,try/catch-em-all 只会阻止运行时提醒您它是错误的。请避免使用两个线程来获得成功。要么让 DataReceived 也处理数据,要么根本不使用 DataReceived,让工作线程调用 Read()。后一种方式生成的代码更容易调试。
  • 实际上锁语句解决了另一个错误。没有它们,一些接收到的字节将被处理两次,我的代码比现在更加错误。我将尝试摆脱出现的串行接收事件。这整个 C# 线程系统是它自己的 IMO 的一个大错误。 @Fildor 我知道,我发布后看到了,我想你在我编辑我的 OP 时回答了,我的错:D
  • @HansPassant 我已将所有内容移至后台工作人员之下。我使用 runWorkercompleted 重新启动后台工作程序。我仍然有完全相同的问题。按下按钮会中断程序的流程

标签: c# serial-port duplex


【解决方案1】:

我终于解决了我的大部分问题。我花了很多时间在谷歌上搜索,但我发现了如何使用 beginInvoke()。与常规 Invoke 不同,beginInvoke 似乎没有那么慢。但是,当机器向我的目标设备发送太多字节时,它仍然会冻结

所以现在我摆脱了后台工作人员并使用它。但我仍然更喜欢使用后台工作人员,因为它对我来说似乎更快。但我不能,我不知道该怎么做。

 private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e) // the Main serial receiving event.
    {
         lock (_lock)
         {
            rxBuffer += serial.ReadExisting();
         }
        serialReceived(rxBuffer);
    }

    private void serialReceived(string value)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke(new serialReceivedDelegate(serialReceived), new object[] { value });
        }
        else
        {
            lock (_lock)
            {

【讨论】:

    猜你喜欢
    • 2016-07-28
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 2013-11-21
    • 2011-07-26
    • 2013-04-01
    • 1970-01-01
    • 2010-11-13
    相关资源
    最近更新 更多