Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 串口连续实时数据#_C#_Wpf_Multithreading_Serial Port_Real Time - Fatal编程技术网

C# 串口连续实时数据#

C# 串口连续实时数据#,c#,wpf,multithreading,serial-port,real-time,C#,Wpf,Multithreading,Serial Port,Real Time,大家好,我正在尝试编写一个简单的C#WPF,它通过计时系统在虚拟记分板上实时显示时间信息。我对编程还比较陌生,希望能有深入的解释 我已经创建了一个新线程来处理来自COM端口的传入数据,随着应用程序的开发,这些数据将被解释。现在,我只想在文本框中显示来自计时器的原始信息(十六进制)。这是可行的,但不是预期的。我收到了大量重复的信息,我唯一的解释是我读取数据的速度太慢,或者它一遍又一遍地读取相同的字节。我想做的是取出每个字节并显示它们,所有这些都由一个启动/停止按钮控制 可能的解决方案包括将整个缓冲

大家好,我正在尝试编写一个简单的C#WPF,它通过计时系统在虚拟记分板上实时显示时间信息。我对编程还比较陌生,希望能有深入的解释

我已经创建了一个新线程来处理来自COM端口的传入数据,随着应用程序的开发,这些数据将被解释。现在,我只想在文本框中显示来自计时器的原始信息(十六进制)。这是可行的,但不是预期的。我收到了大量重复的信息,我唯一的解释是我读取数据的速度太慢,或者它一遍又一遍地读取相同的字节。我想做的是取出每个字节并显示它们,所有这些都由一个启动/停止按钮控制

可能的解决方案包括将整个缓冲区存储在一个列表或数组中,我还不太确定,我不想添加太多线程,以至于程序冻结所有内容

这是我迄今为止的代码(我对这里编写的几乎所有代码都是新手,因此如果有任何不好的做法,请让我知道):

这里有一个解决方案

串行端口在其自己的线程中接收数据,您应该在数据接收处理程序中读取传入字节

我建议读取数据并将其添加到数据接收处理程序中的线程安全FIFO列表中,然后从主线程中的列表中读取数据


请参阅我在文章中的解决方案

ConsoleBox是GUI控件(TextEdit?)吗?请注意GUI绘制,尤其是更新文本内容,与通常的处理器任务相比,速度非常慢。一个简单的解决方法是使用stringbuffer,并在单独的计时器上显示它。event.Yes抱歉ConsoleBox是一个文本框,我不知道为什么命名它。。这个计时器事件是什么?它需要在另一个线程上运行吗?线程是否必须在双核CPU上交换,我会丢失数据?只需使用一个简单的计时器控件并将其间隔设置为1秒,然后在计时器事件期间将stringbuffer的内容写入文本框。当然,您是对的:您必须使用beginInvoke执行此线程安全访问,就像您在上面的代码中所做的那样。argh很抱歉,您是在wpf而不是winforms世界中!请使用Dispatchermer,如图所示:我以前使用过winforms定时器,它看起来是一种类似的方法。谢谢你的帮助!嗨,谢谢你的回复。我尝试使用您的想法,它在一定程度上起到了作用,我实现了一个计时器来显示数据,但是它只显示第一次滴答的数据,然后当我尝试停止时,应用程序冻结。不过,我正在使用的十六进制看起来是正确的。当您进入计时器计时处理程序时,请在调用例程清空队列之前停止计时器。当队列为空且例程返回时,再次启用计时器。这就是我所做的,以确保计时器滴答事件不会调用得太早。谢谢!通过将队列中的所有内容取出并将其放入另一个中间数组以防止死锁,然后使用stringbuilder显示数据,我可以使它顺利工作。进入下一步!伟大的对于从微控制器接收数据的应用程序,我每10毫秒有一个计时器事件。串行端口设置为9600波特,队列永远不会变大,但我用接收到的字符而不是一次一个字符对结构进行排队,这有助于更有效地解排队。
public partial class MainWindow : Window
{
    SerialPort comms;
    Thread commThread;

    bool flag;
    string message;


    public MainWindow()
    {
        InitializeComponent();
        comms = new SerialPort();
    }

    private void PortControl_Click(object sender, RoutedEventArgs e)
    {
        if (!comms.IsOpen)
        {
            PortControl.Content = "Stop";
            comms.PortName = "COM1";
            comms.BaudRate = 9600;
            comms.DataBits = 8;
            comms.StopBits = StopBits.One;
            comms.Parity = Parity.Even;
            comms.ReadTimeout = 500;
            comms.ReceivedBytesThreshold = 1;

            commThread = new Thread(new ThreadStart(Handle));

            comms.Open();

            comms.DataReceived += new SerialDataReceivedEventHandler(ReadIn);
        }
        else
        {
            PortControl.Content = "Start";
            flag = false;
            comms.DataReceived -= ReadIn;

            commThread.Join();
            comms.Close();
        }
    }

    private void ReadIn(object sender, SerialDataReceivedEventArgs e)
    {
        if (!commThread.IsAlive)
        {
            flag = true;
            commThread.Start();
        }
    }

      private void Handle()
      {
          while (flag)
          {
              if (comms.IsOpen)
              {
                  try
                  {
                      message = comms.ReadByte().ToString("X2");

                      Dispatcher.BeginInvoke((Action)(() =>
                      {
                          ConsoleBox.Text += message + " ";
                      }));
                  }
                  catch (Exception ex)
                  {
                      MessageBox.Show(ex.ToString());
                  }
              }
          }
      }


}