我在C#中用serialport控件实现了一个串口小程序,具体如下:
1.该程序每100ms发出一个命令给外部接收设备,由一个timer控制
2.设置串口接收的ReceivedBytesThreshold为1,即每接收到一个字节就触发DataReceive事件,DataReceive事件代码如下:
public void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            long lExecuteTime = 0;            // modified trigger condition to maximum time
            serialPort1.ReceivedBytesThreshold = serialPort1.ReadBufferSize;            int curbyte = serialPort1.ReadByte();            recvbuf[iCurPos++] = (byte)curbyte;            if (curbyte == 0x7E)    // received a completed response
            {
                EndTime = DateTime.UtcNow;
                timer_timeout.Enabled = false;                lExecuteTime = (EndTime.Ticks - StartTime.Ticks) / 10; // change to us
                lb_time.Text = lExecuteTime.ToString() + " us";                InforDisplay(recvbuf, iCurPos);
                iCurPos = 0;
            }
            else if (iCurPos > 79)
            {
                txtBox_Err.Text += "Error: Receive buffer over flow!\r\n";                iCurPos = 0;
            }            // recover trigger condition to 1
            serialPort1.ReceivedBytesThreshold = 1;
         }这其中调用了一个函数InfoDisplay, 这个函数用来将接收到的数据显示到界面上。3. 问题:程序运行之后,命令收发正常,显示也正常;但是当鼠标在窗体上移动时,串口数据就会有丢失的可能,鼠标移动的越快,出错几率越大。我推断,鼠标移动时,程序要响应mousemove事件(我并没有处理这个事件),导致来不及响应datareceive事件,造成数据丢失4. 从网上查,用多线程可以解决这个问题,但是我不知道该怎么设计这个多线程,请大家指点多谢串口接收数据鼠标移动多线程C#

解决方案 »

  1.   

    http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport.datareceived.aspx你的响应函数每次只读一个字节,是可能会"丢失数据"。
    建议按照MSDN的方法进行改进。
      

  2.   

    其实这个和你鼠标没有任何关系,这样使用是一定有问题的。
    接收事件里不要做处理,只接收就好了,接收事件中有比较耗时的处理逻辑都会导致丢数据。处理要另开线程。具体原因不清楚,我觉得使用事件接收后,串口软件缓冲都无效了,无论设置多大的缓冲,都会丢数据。txtBox_Err.Text += "Error: Receive buffer over flow!\r\n";这个有问题,不要操作UI控件,接收事件不在主线程中,没有同步非UI线程操作UI控件会出错的。最简单的使用方法是使用一个Timer 定期检查串口有没有数据,如果有的话就读出来处理。
            private void timer1_Tick(object sender, EventArgs e)
            {
                if (serialPort1.BytesToRead > 0)
                {                byte[] buffer = new byte[serialPort1.BytesToRead];
                    serialPort1.Read(buffer, 0, buffer.Length);
                    // 处理........
                }
            }
      

  3.   

    为啥非要1个字节就触发事件呢?线程读取 串口中有多少读多少,直到读不到,然后开始处理数据。如果使用线程调用界面刷新,需要Invoke方法。
    个人认为,你不用设置1字节 触发接收事件 就OK的。