最近老板要求搞一个实时读取人体信号并显示的模块,但小弟刚入门C#,目前遇到点问题,尝试了一些方法还是解决不了,求大佬帮忙解答。
下位机单片机作为服务器,采集信号后传送给PC端显示。但是可能由于数据量太过庞大,每次接收显示的数据只有一点点,不能一直传输。按老板的要求,至少需要采集几个小时的肌电信号。所以目前很懵逼,求解答~下面把代码贴上来

解决方案 »

  1.   

    这是timer定时读取数据
    private void timerByClient_Tick(object sender, EventArgs e)
            {
                try
                {
                    lock (nsClient)
                    {
                        if (nsClient != null && nsClient.CanRead)
                        {
                            if (nsClient.DataAvailable)
                            {
                                BeginReadServerMsg(nsClient);
                                ShowDataStat();
                            }
                        }
                    }
                }
                catch (ObjectDisposedException ex)
                {
                    MessageBox.Show("数据无法读取,流对象已被销毁或与服务端已断开连接!详细信息:" + ex.ToString());
                }
            }
      

  2.   

     #region 读取来自下位机服务器的数据
            delegate void UpdateData(byte[] byteData);//声明一个委托
            //byte[] byteTemp;
            /// <summary>
            /// 读取来自服务器的数据
            /// </summary>
            /// <param name="nsClient"></param>
            public void BeginReadServerMsg(NetworkStream nsClient)
            {
                byte[] byteTemp = new byte[1000];  //字节buffer
                //锁定客户端网络工作流
                lock (nsClient)
                {
                    try
                    {
                        if (nsClient.CanRead && nsClient.DataAvailable)
                        {
                            //保存从流中读取的字节数
                            int readSize = 0;
                            //保存从流中读取的总字节数
                            int totalSize = 0;
                            nsClient.ReadTimeout = 100;
                            nsClient.WriteTimeout = 100;
                            //创建临时保存每次读取数据的流对象
                            MemoryStream ms = new MemoryStream();
                            while (nsClient.DataAvailable)
                            {
                                byte[] msgByte = new byte[819200];
                                readSize = nsClient.Read(msgByte, 0, 819200);
                                while (readSize == 0) //如果接收到的有效字节数为0 说明服务器已经关闭了。这时候就跳出循环了。  
                                {
                                    //如果为0重新读取  
                                    continue;
                                }
                                totalSize += readSize;
                                ////写入临时流中用于一次性全部读取数据
                                ms.Write(msgByte, 0, readSize);
                            }
                            msgBytesByServer = new byte[totalSize];
                            byteTemp = new byte[totalSize];  //字节buffer
                            ms.Position = 0;                        ////将ms临时流中保存的数据全部读出
                            int readAllSize = ms.Read(msgBytesByServer, 0, totalSize);
                            while (readAllSize >= 18)
                            {
                                UpdateData Update = new UpdateData(DecodeData);
                                msgBytesByServer.CopyTo(byteTemp, 0);
                                //string msg=System.Text.Encoding.Default.GetString(byteTemp);
                                //lbsClient.Text = msg + "\n\r";
                                if (!((byteTemp[0] == 0x82) & (byteTemp[17] == 0xff)))
                                {
                                    for (int i = 1; i < readAllSize; i++) msgBytesByServer[i - 1] = msgBytesByServer[i];
                                    readAllSize--;
                                    continue;
                                }
                                Invoke(Update, byteTemp);
                                for (int i = 18; i < readAllSize; i++) msgBytesByServer[i - 18] = msgBytesByServer[i];
                                readAllSize -= 18;
                            }
                            String serverMsg = Encoding.Default.GetString(msgBytesByServer, 0, msgBytesByServer.Length);
                            nsClient.Flush();
                            ms.Close();
                        }
                    }
                    catch (SocketException ex)
                    {
                        MessageBox.Show("读取来自服务器的数据发生异常,详细信息:" + ex.ToString());
                    }
                }
            }
      

  3.   

    DecodeData这个委托实现的是解析绘图功能
      

  4.   

    怎么可能定时器驱动呢?既然你 BeginXXXXX 异步驱动数据读取,那么当消息来了之后,快速缓存了读取到的数据之后,才开始下一个 BeginXXXX 注册。这是一个连续的动作。如果异步驱动跟定时器驱动混在一起,就不论不类了,而且相互干扰、阻抗放大了你的问题。
      

  5.   

    除了异步读取数据的模式以外,最基本的通讯设计模式还包括要处理粘包和分包的情况,如果没有这方面的代码,说明也是很多很多 bug 的。
      

  6.   


    但是我现在把定时器去掉之后,程序就会一直卡死在if (nsClient.CanRead && nsClient.DataAvailable)这个地方 ,dataailable一直返回null 这是为什么?
      

  7.   

    只是读而已嘛,又不用保存,显示也没必要太频繁,要符合人的眼睛,你只要刷屏时读取数据就够了,可以考虑清空当前缓存数据,等待下一个数据到达。截断关键还是数据太快太多,socket到极限了吧。
      

  8.   

    最简单的是写死循环读数据 如
    LIst<byte[]> a
    while(true)
     {
     lock(a){ 
     a.add(     TCPCLient.Read...)
    }
    }然后在另一个线程中使用
    循环取a  里的数据就行了
     
      

  9.   

    当你收到数据,你就把数据放到缓冲,然后判断有没有完整的消息,如果有完整的消息就异步解析执行消息命令;同时并不阻塞处理下一个收到的数据。弄一个循环以及 10 几年前一些 java 和少量 c++ 书中所谓“生产者-消费者模式”虽然很初级很好理解,但是其实是堵塞、混乱、繁琐的代码根源。