Модераторы: gambit, Kefir, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Данные от USB устройства в UI в реальном времени 
:(
    Опции темы
Aldegid
Дата 24.8.2012, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.6.2011

Репутация: нет
Всего: нет



Всем привет.

У меня есть USB устройство и мне нужно отображать данные от него в окне. Работает, но медленно. 

Тему "отображение данных в окне в реальном времени" http://forum.vingrad.ru/topic-332264.html читал, но ответа не нашел.

У меня есть некое USB устройство, с которым я общаюсь через класс SerialPort. При открытии порту назначается скорость 115200. Мне нужно получать от него данные и отображать их в двух TextBox'ах в реальном времени. Я подписываюсь на событие DataReceived
Код

        _port.DataReceived += OnRunningDataReceived;

И прослушиваю устройство
Код
      
    // класс, общающийся с утройством
    public partial class DeviceCommunicator
    { 
        private void OnRunningDataReceived( Object sender, SerialDataReceivedEventArgs e )
        {
            // пока есть данные в буфере чтения устройства
            while( _port.BytesToRead >= PacketSize )
            {

                // выделим буфер
                Byte[] buffer = new Byte[PacketSize]; /* todo: оптимизировать выделение new каждый раз */
                // попробуем прочитаем наш пакет измерений
                if( !Read( buffer, 0, WeightPacketSize, _runningPacketErrorCallback ) )
                        // ...

                // проверим маркеры и счетчик
                // ... операции, которые не должны занимать много времени

                // декодируем значения 
                // ... еще операции, которые не должны занимать много времени

                // вызовем отдадим данные наружу
                _runningPacketReceivedCallback( ws, pc ); // Callback, описанный ниже
            }
        }
    }

Окно должно отображать данные
Код

    // класс окна
    public partial class MainWindow : Window
    {
        private void OnMeasuresReceived( Ws ws, PC pc )
        {
            // выставим control'ы в соответствии с полученными значениями
            Dispatcher.Invoke( (Action)( () =>
                {
                    _xTextBox.Text = pc.x.ToString();
                    _yTextBox.Text = pc.y.ToString();
                } ), null );
        }
    }


Так вот, несмотря на то, что за секунду приходит около 50 паектов данных, отображаются примерно 2-3 (определено на глаз), отображаются несинхронно (сначала меняется значение _xTextBox, потом, через долю секунды _yTextBox), неравномерно (между сменой значений проходят разные интервалы времени: от трети секунды до секунды), входной буфер устройства забивается.

Насколько я понимаю, тормозит вызов Dispatcher.Invoke. Сейчас уже понял, что мне придется делать какое-то сглаживание, даже если удастся добиться, чтобы данные отображались в реальном времени в textBox'ах, но все равно,
подскажите, как лечить.

Это сообщение отредактировал(а) Aldegid - 24.8.2012, 09:04
PM MAIL   Вверх
erm0l0v
Дата 24.8.2012, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: нет
Всего: 1



Просто Dispatcher.Invoke так работает. Вы передаете ему Action, но это не значит что он сразу побежит его выполнять. Он поставит ваш Action в очередь и когда не будет других более приоритетных заданий Action будет выполнен. Попробуйте изменить приоритет вашего Dispatcher.
PM MAIL   Вверх
Aldegid
Дата 24.8.2012, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.6.2011

Репутация: нет
Всего: нет



Попробовал повысить приоритет до максимального. Стало немногим быстрее. Но это меня не устраивает. Как-то это для меня очень странно. У меня есть приложение с UI, но этот UI я обновлять не могу в том темпе, который мне нужен... Хоть переписывай под Windows Forms.
PM MAIL   Вверх
erm0l0v
Дата 24.8.2012, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: нет
Всего: 1



Ну в этом есть определеная логика. Зачем обновлять данные быстрее чем пользователь сможет их прочитать.
На крайний случай вы можете не использовать Dispatcher, а вычислять данные в потоке формы, но скорее всего из-за этих дейсвий интерфейс перестанет реагировать на пользователя.
Еще можно использовать DispatcherTimer, и показывать актуальное значение в момент срабатывания таймера, но в таком случае некоторые значения могут так и не оказаться на форме.
PM MAIL   Вверх
Aldegid
Дата 24.8.2012, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.6.2011

Репутация: нет
Всего: нет



erm0l0v, согласен. Но дело, кажется в другом.

Еще на одном форуме я жаловался, что VS как-то странно работает с этим WPF. Сначала я переименовал созданный control, попробовал написать его идентификатор в тексте - и не IntelliSense, ни компилятор его не нашли. А потом через несколько минут нашли.

Потом я добавил обработчик нажатия кнопки, поставил туда точку останова, запустил, нажал на кнопку - точка останова не сработала.

Насколько я понимаю, в студии с этим WPF намудрен какой-то не для простых смертных механизм синхронизации. И компилятор и IntelliSense узнают об изменениях, внесенных в XAML далеко не сразу  >:(((((((( 

Теперь вот подергал XAML еще немного - TextBox'ы стали обновляться быстро. ###.
PM MAIL   Вверх
erm0l0v
Дата 24.8.2012, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: нет
Всего: 1



Видимо вы используете при разработке на WPF тот же подход, что и при разработке в WF.

В этом случае конечно будут незаметны все прелести WPF и технологии XAML по сравнению с разработкой через события в WF. Я при разработке в WPF использую шаблон MVVM, и в лучших традициях этого шаблона код в .xaml.cs вообще не трогаю.

У меня с IntelliSense все нормально, правда нужно постоянно делать ребилд чтобы студия узнала о новых изменениях, но это нормально.

В вложении кинул свою реализацию задачи с помощью MVVM.

Это сообщение отредактировал(а) erm0l0v - 24.8.2012, 13:16

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  TestUpdate.rar 65,82 Kb
PM MAIL   Вверх
Aldegid
Дата 27.8.2012, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.6.2011

Репутация: нет
Всего: нет



erm0l0v, наконец-то добрался до Вашего примера. Посмотрел на бегущие счетчики, посмотрел, что совсем нет привычного C# кода, и не понял, как предложенный Вами подход работает, чего он позволяет достичь, и в чем его преимущества.

Поясните или дайте ссылку или запрос для поисковика, пожалуйста.
PM MAIL   Вверх
erm0l0v
Дата 27.8.2012, 15:07 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: нет
Всего: 1



Даже не знаю не какой хорошей ссылке где это все было просто и понятно написано, хотя статей очень много по теме, ключевые слова WPF Binding MVVM.

В примере я разделил код на представление(MainWindow.xaml) и модель(MainViewModel.cs). 
MainWindow.xaml отвечает только за отображение
в MainViewModel.cs находится вся логика. Традиционно модель наследуется от интерфейса INotifyPropertyChanged, который содержит одно единственно событие, сигнализирующее о изменении свойства модели. У меня модель унаследована от BaseViewModel.cs там реализованы дополнительные синтаксические плюшки, но можно обойтись и без них.

И так в нашей модели есть свойства X Y которые будут отображаться, с вызовом метода OnPropertyChanged в сетере, который в свою очередь вызывает событие интерфейса INotifyPropertyChanged. То есть как только мы меняем например свойство X событие PropertyChanged сигнализируют нашему представлению что нужно перерисовать все элементы в которых задействовано X.

Элементы X Y у меня меняются в потоке thUpdate который запускается при нажатии на кнопку Start.

Далее идем к нашему представлению. Во первых в представлении необходимо указать модель, за это отвечает свойство DataContext. Я унаследовал  BaseViewModel от MarkupExtension который возвращает сам себя, благодаря этому я проициализировал DataContext одной строчкой:
Код

<Grid DataContext="{viewmodel:MainViewModel}">

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

Можно было и без этого, например создать MainViewModel в ресурсах окна, или в коде в файле MainWindow.xaml.cs, но мне кажется так удобнее.
Далее у нас идет обычная разметка страницы, и там где необходимо мы привязываем свойства нашей модели с помощью Binding. Например код TextBlock который будет отображать значение X выглядит так:
Код

<TextBlock Text="{Binding X}" />

Здесь мы говорим что хотим чтобы в поле Text отображалось значение X, и при этом при изменении значения X Text будет автоматически обновляться.

С кнопкой все аналогично, только мы биндимся на свойство Start типа ICommand.

В принципе все.

По поводу преимуществ, самое главное это то что мы разделяем представление и реализацию, в результате мы можем заменить без проблем и то и другое, использовать UnitTest, да я сам код выглядит чище и понятнее.
Плюс там есть еще очень много плюшек, такие как валидация, DataTemplate и другое, что делает нашу жизнь слаще)))

Если вы решите использовать такой же подход, то после месячной ломки вы в него влюбитесь и будете смотреть на программистов которые разрабатывают UI через событие как на пещерных людей.
PM MAIL   Вверх
Aldegid
Дата 28.8.2012, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.6.2011

Репутация: нет
Всего: нет



Ну да, в свое время я немножко затронул шаблон MVC. Было в нем что-то. Но как-то пока это для меня грузновато. Ни одного класса из перечисленных не знаю. Наверняка Вы написали этот пример раньше и не для меня одного. Ну или большую часть.

Я думал, какой же компонент выбрать для отображения графика данных, постапающих в реальном времени. Теперь еще нужно думать, как его всунуть в этот шаблон.  smile  smile 
PM MAIL   Вверх
erm0l0v
Дата 28.8.2012, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 157
Регистрация: 11.1.2011

Репутация: нет
Всего: 1



Про графики можно посмотреть здесь.

Если вы в качестве коллекции данных для графика будите использовать ObservableCollection<T>, то график будет обновляться после каждого изменения коллекции.
PM MAIL   Вверх
Aldegid
Дата 29.8.2012, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.6.2011

Репутация: нет
Всего: нет



При всем моем уважении: 17:40
Цитата
Процессор используется сейчас на 30%. Все из-за того, что у нас такое приложение (три графика на 15 точек каждый, обновляеся раз в полсекунды). Надо опрашивать пореже, наверно. Не раз в полсекунды. Ну это всего лишь пример. Таким образом Вы можете сделать красивое удобное приложение.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




[ Время генерации скрипта: 0.1364 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.