2013-06-01 4 views
1

Привет Я пытаюсь запрограммировать простой C# WPF, который отображает информацию о времени на виртуальной табло в режиме реального времени из системы синхронизации. Я довольно новичок в программировании, поэтому углубленное объяснение будет оценено по достоинству.serialport непрерывные данные реального времени C#

Я создал новый поток для обработки входящих данных с COM-порта, и по мере того, как приложение будет разработано, эти данные будут интерпретироваться. На данный момент я просто хотел отобразить необработанную информацию (в шестнадцатеричной форме), которая поступает из таймера в текстовое поле. Это работает, но не так, как предполагалось. Я получаю тонны повторяющейся информации, мое единственное объяснение - это слишком медленно читать данные или читать один и тот же байт снова и снова. То, что я хотел бы сделать, - вынуть каждый байт и отобразить их, все управляемые одной кнопкой запуска/остановки.

Возможные решения включают хранение всего буфера в списке или массиве, который я еще не совсем уверен, я не хочу добавлять столько потоков, что программа замерзает все.

Вот мой код до сих пор (я новичок в значительной степени весь код, я написал здесь, так что если что-то плохая практика, пожалуйста, дайте мне знать):

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()); 
        } 
       } 
      } 
     } 


} 
+0

Является ConsoleBox с графическим интерфейсом управления (TextEdit?) Обратите внимание, что Гуй живопись, особенно обновления текста-контента, как вы делали __extremely__ замедлится по сравнению с обычными задачами процессора. Одно простое обходное решение действительно использует stringbuffer и просто отображает это на отдельном timer.event. – Enno

+0

Да, жаль, что ConsoleBox - это TextBox. Я не знаю, почему я назвал его тем. Что это за событие Timer, нужно ли продолжать другой поток? Не будут ли потоки заменяться на двухъядерный процессор и я потеряю данные? – pgwri

+0

просто используйте простой таймер-контроль и установите его интервал на одну секунду, затем во время события таймера запишите содержимое вашего буфера строк в текстовое поле. конечно, вы правы: вам нужно выполнить этот потоковый доступ, например, с beginInvoke, как вы уже делали в своем коде выше. – Enno

ответ

0

Вот одно решение.

Последовательный порт принимает данные в своем потоке, и вы должны прочитать входящие байты в обработчике данных.

Предлагаю прочитать данные и добавить их в потокобезопасный список FIFO в обработчике данных и прочитать данные из списка в основном потоке.

Смотрите мое решение в пост Serial port reading + Threads or something better?

+0

привет спасибо за ответ. Я попытался использовать вашу идею, и она работает до некоторой степени, я применил таймер для отображения данных, однако он отображает только мои данные для первого тика, а затем, когда я пытаюсь остановить его, приложение замерзает. Шествие, которое я получаю, выглядит правильным. – pgwri

+0

Когда вы вводите обработчик тикового таймера, остановите таймер перед вызовом процедуры, чтобы освободить очередь. Когда очередь пуста и процедура возвращается, снова включите таймер. Это то, что я делаю, чтобы убедиться, что событие таймера не вызвано слишком рано. – user2019047

+0

Спасибо!Я смог заставить его работать плавно, вынимая все из очереди и помещая его в другой промежуточный массив, чтобы предотвратить блокировку, а затем с помощью строкового редактора для отображения данных. На следующий шаг! – pgwri

Смежные вопросы