2014-11-08 9 views
0

я беру над C код # от кого-то, кто реализованного приложение с рабочего стола, чтобы прочитать реальные данные о времени от последовательного порта и отображения его на графиках (используя Chart Класс).C# в режиме реального времени график настольное приложение слишком медленно

Код, похоже, работает, но очень медленно. Кажется, что обновление графика происходит примерно раз в 4 секунды (0,25 Гц). Тем не менее, я вижу, что он многопоточен и не имеет команд задержки, поэтому я не понимаю, почему он работает так медленно. Может ли обновление диаграмм замедлить его? В идеале я хотел бы достичь 1000 точек данных в секунду (1кГц), отображая его в реальное время и экономии его на жесткий диск, где размер каждой точки составляет около 30 байт.

Я провел несколько дней, понимая код, но это слишком громоздко, чтобы следовать, все написано в одном файле без комментариев. Является ли моя цель читать 1000 точек данных в секунду реалистично/достижимо?

Я также рассматривает возможность переписать код (в отличие от попытки исправить это), полагая, что это всего лишь около 2500 линии долго. Любые советы будут оценены. Кроме того, если я переписал код , какой язык может быть лучше для этого приложения?

+1

Вы серьезно? 30Bytes * 1000data/sec с использованием последовательного порта? нет, не реально! вы можете переписать код, если хотите, но вы должны снова рассмотреть свои спецификации, можете ли вы рассказать мне, какова ваша скорость? – chouaib

+0

Действительно ли это 30 кБ/с? В настоящее время скорость составляет 38400. Но она будет соответственно увеличена. Меня не так беспокоит аппаратное обеспечение. Интересно, может ли «обычный» компьютер (i7 3Ghz 8G ram) следить за отображением и сохранением графика в реальном времени. –

+0

Это 30 000 байт/с, что составляет 240 000 бит в секунду. Самая высокая скорость передачи по сравнению с последовательным портом, который я видел, составляет 230 400 бит в секунду, что просто застенчиво от вашего требуемого сквозного прохода. –

ответ

0

Я предполагаю, что вы используете Winform приложения:

Используйте serialPort компонент:

  1. Сконфигурируйте его properties: (BaudRate, бит данных, стоповый бит, контроль четности ...) использование
  2. сделать из его event (DataReceived) для сбора ваших входных данных.

Вы можете посылать команды в цикле и собирать входы/вовлекая их на графике компонента примерно так:

while(/*some condition*/) 
{ 
    serialPort.Write(/* your command */); 

    // you have to think of response time 
    // so implement something that waits a bit before calling the port again 
    // I would do it using timers 

    int tick= Environment.TickCount; 
    while(Environment.TickCount - tick <= 100) // wait 100 milliseconds 
    { 
    Application.DoEvents(); 
    } 

} 

// collect the data as: 
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    // use according to your needs, for example 
    string data = ""; 
    int readByte; 
    int available; 

    available = serialPort.BytesToRead; 
    if(available >= 30) // 30 bytes as stated in your question 
    { 
    for(int i=0; i<30; i++) 
    { 
     readByte = serialPort.ReadByte(); 
     data += String.Format("{0:2X}", readByte); 
    } 

    // you can call some methods to save/display your collected data from here 
    save_to_file(data); 
    display_to_chart(data); 
    } 

} 
1

Я разработал код, где я получил значительное улучшение производительности, он может работать для вас. Вот что я did-

Шаг 1: Сначала я хотел бы определить, какой из них является горлышко бутылки, drawing/rendering of the chart

илиserial port

Шаг 2: Если вы нашли сво rendering-- тогда добавьте это в свою форму/схему диаграммы, она будет рисоваться намного быстрее. Но сначала проверьте, чтобы убедиться, что вы не находитесь в режиме удаленного рабочего стола.

<!-- language: c# --> 

    // No double buffering for remote, only local 
    public bool OptimizeOfLocalFormsOnly(System.Windows.Forms.Control chartControlForm) 
    { 
    if (!System.Windows.Forms.SystemInformation.TerminalServerSession) 
    { 
       SetUpDoubleBuffer(chartControlForm); 
       return true; 
    } 
    return false; 

    } 

    public static void SetUpDoubleBuffer(System.Windows.Forms.Control chartControlForm) 
    { 

     System.Reflection.PropertyInfo formProp = 
     typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered",   System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);  
     formProp.SetValue(chartControlForm, true, null); 
    } 
0

Я разработал аналогичное приложение, в котором я показывал 16 карт * 256 выборок в секунду. Хранение данных в буфере и создание отдельного потока для обновления диаграмм, сработанных для меня.

Когда новые данные считываются, данные хранятся в списке или массиве.Так как это данные в реальном времени, здесь также создаются временные метки. Использование частоты дискретизации полученных данных: timeStamp = timeStamp + sampleIdx/sampleRate;

public void OnDataRead(object source, EEGEventArgs e) 
     { 
      if ((e.rawData.Length > 0) && (!_shouldStop)) 
      { 
       lock (_bufferRawData) 
       { 
        for (int sampleIdx = 0; sampleIdx < e.rawData.Length; sampleIdx++) 
        { 
         // Append data 
         _bufferRawData.Add(e.rawData[sampleIdx]); 

         // Calculate corresponding timestamp 
         secondsToAdd = (float) sampleIdx/e.sampleRate; 

        // Append corresponding timestamp 
        _bufferXValues.Add(e.timeStamp.AddSeconds(secondsToAdd)); 
        } 
       } 

Затем создать поток, который спит каждую N мс (100 мс подходит для меня дисплей 2 секунды данных, но если я хочу дисплей 10 секунд, мне нужно увеличить до 500мс времени сна для нить)

//Create thread 
//define a thread to add values into chart 
ThreadStart addDataThreadObj = new ThreadStart(AddDataThreadLoop); 
_addDataRunner = new Thread(addDataThreadObj); 
addDataDel += new AddDataDelegate(AddData); 

//Start thread 
_addDataRunner.Start(); 

и, наконец, обновление карт и сделать поспать нить, каждый N мс

private void AddDataThreadLoop() 
    { 
     while (!_shouldStop) 
     { 
      chChannels[1].Invoke(addDataDel); 

      // Sleeep thread for 100ms 
      Thread.Sleep(100); 
     } 
    } 

метод AddData, просто считывает X (метки времени) и значения Y сохраняются в буфере и объявления d его к диаграммам с использованием ptSeries.Points.AddXY (xValue, yValue)

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