Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Быстрый вывод данных из потока

09.09.2016, 08:11. Показов 1712. Ответов 24
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую. Для максимально быстрого вывода данных из потока в окно я создал нижеприведенный шаблон. В классе потока созданы переменные по данному шаблону, значения которых нужно выводить в окно. В процедуре, вызываемой через Synchronize, вывод данных в окно осуществляется только в том случае, если соответствующая переменная была обновлена в потоке.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <typename Type> class UpdateVariable
{
 private:
  Type FValue;
  bool FIsUpdate;
 
  Type GetValue()               { FIsUpdate = false; return FValue; };
  void SetValue(Type Value_)    { FIsUpdate = true; FValue = Value_; };
 
 public:
       UpdateVariable()         { FIsUpdate = false; }
 
  __property Type Value       = { read = GetValue, write = SetValue };
  __property bool IsUpdate    = { read = FIsUpdate };
  void operator = (Type Value_) { SetValue(Value_); };
};
Оцените, пожалуйста, подобную реализацию вывода информации из потока. Может зря я сделал шаблон и существует "изобретенный велосипед"? Или вывод информации из потока можно (или даже нужно) выполнить по-другому? Или может все хорошо, но шаблон надо исправить?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.09.2016, 08:11
Ответы с готовыми решениями:

Быстрый вывод jpeg на экран
В продолжении темы https://www.cyberforum.ru/cpp-builder/thread1543958.html Очень долго происходит jpeg-&gt;LoadFromStream(as); ...

Быстрый вывод данных в TextArea (FXML)
Добрый вечер! Прошу о помощи знатоков Java (в частности JavaFX, FXML). Пишу программу что-то наподобие монитора последовательных COM...

Вывод данных в richTextBox из потока
Помогите с этим.. выпадает исключение на последней строке StackOverflowException. Программа создает поток в котором происходит циклическое...

24
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33377 / 21501 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
09.09.2016, 10:50
Ты бы примеры использования показал, тогда будет понятно, надо оно или нет...
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.09.2016, 11:16  [ТС]
Примерно вот так применяю:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* Объявление переменных в хедере класса потока*/
UpdateVariable<String>            Caption;             //Заголовок окна
UpdateVariable<String>            pTask_Caption;       //Информация о текущей задаче
UpdateVariable<String>            pResult_Caption;     //Информация о результате выполнения задачи
UpdateVariable<int>               pbProgress_Max;      //Конечное значение полосы прогресса
UpdateVariable<int>               pbProgress_Position; //Текущее положение полосы прогресса
 
 
/* Функция обновления данных в окне */
void __fastcall TThreadM230::RefreshProgressForm()
{
 if(Caption.IsUpdate)             ProgressForm->Caption              = Caption.Value;
 if(pTask_Caption.IsUpdate)       ProgressForm->pTask->Caption       = pTask_Caption.Value;
 if(pResult_Caption.IsUpdate)     ProgressForm->pResult->Caption     = pResult_Caption.Value;
 if(pbProgress_Max.IsUpdate)      ProgressForm->pbProgress->Max      = pbProgress_Max.Value;
 if(pbProgress_Position.IsUpdate) ProgressForm->pbProgress->Position = pbProgress_Position.Value;
}
 
 
/* Применение в главной функции потока */
void __fastcall TThreadM230::Execute()
{
 Caption = L"Чтение данных";
 pTask_Caption = L"Чтение почасовых данных";
 pbProgress_Max = 1000;
 
 while(!Terminated || ReadData() != 0)
  {
   pResult_Caption = L"Прочитано: " + String(ReadData());
   pbProgress_Position.Value++;
   Synchronize(&RefreshProgressForm);
  }
}
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 11:55
d7d1cd, не хочу расстраивать, но таки велосипед. Абсолютно ненужная проверка IsUpdate, так как такая проверка встроена внутрь write-методов Caption, Position и т.д.

C++
1
__property TCaption Caption = {read=GetText, write=SetText, stored=IsCaptionStored};
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
procedure TControl.SetText(const Value: TCaption);
begin
  // здесь будет выполнена проверка, что пришло новое значение
  if GetText <> Value then
{$IF DEFINED(CLR)}
  begin
    FText := Value;
    Perform(CM_TEXTCHANGED, 0, 0);
  end;
{$ELSE}
  SetTextBuf(PChar(Value));
{$IFEND}
end;
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33377 / 21501 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
09.09.2016, 12:04
Цитата Сообщение от Maluda Посмотреть сообщение
такая проверка встроена внутрь write-методов
Не для этого она используется у ТС-а, а для того, чтобы показать, нужно ли заново получать/отображать объект через Synchronize. Если получаем значение объекта - то только для того, чтобы его отобразить на форме. При этом сбрасываем IsUpdate, и если в следующий раз опять нужно обновить форму, то неизмененные объекты не обновляем.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.09.2016, 12:06  [ТС]
Maluda, спасибо за показ велосипеда! Получается, что если в компоненте изменяется какое-либо из его свойств и новое значение равно уже установленному, то перезаписи этого значения не будет происходить? Так сделано во всех компонентах и со всеми свойствами?

Добавлено через 1 минуту
volvo, так применение шаблона у меня оправдано? Ведь как показал Maluda такая проверка уже идет внутри компонента.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 12:09
П.С. Из приёмов быстродействия я бы предложил ограничение по количеству выводов, к примеру у тебя данные приходят 60 раз в секунду и при нынешнем твоём коде ты будешь 60 раз в секунду перерисовывать заголовок, хотя 20 раз в секунду вполне хватит, ну и т.д. Или завести таймер, который будет срабатывать, например, 20 раз в секунду, собирать все последние данные и обновлять всё.

Добавлено через 1 минуту
volvo, код смотрите внимательно. У него Synchronize вызывается в любом случае, что определенно тормозит программу
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33377 / 21501 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
09.09.2016, 12:10
Цитата Сообщение от d7d1cd Посмотреть сообщение
проверка уже идет внутри компонента
Это не такая проверка. Та проверка никакого отношения к твоему функционалу не имеет. У тебя нет возможности определить, было ли изменено значение объекта, кроме как добавив свою прослойку и изменив геттер/сеттер, что у тебя и делается. Работает - значит оправдано. Удобнее - значит оправдано. Не слушай никого, кто будет тебя убеждать в обратном. Работать с проектом тебе, а не им. И если твой шаблон экономит тебе тысячи строк кода - почему бы и нет?
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 12:13
Цитата Сообщение от volvo Посмотреть сообщение
Это не такая проверка
Мне кажется, или у вас позиция лишь бы что-то сказать, но не так как у меня?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33377 / 21501 / 8236
Регистрация: 22.10.2011
Сообщений: 36,896
Записей в блоге: 11
09.09.2016, 12:16
Цитата Сообщение от Maluda Посмотреть сообщение
код смотрите внимательно
Это к вам тоже относится. Просто вызвать процедуру через Synchronize и при этом еще в этой процедуре получить/обновить пять свойств (это если без шаблона) или два (это если с шаблоном) - это ОЧЕНЬ разные вещи. Не там ищем блох. Основное замедление будет как раз за счет увеличения "вхолостую" вызываемых геттеров/сеттеров для объектов, которые будут вызываться, если убрать guardian в виде IsUpdate

Добавлено через 2 минуты
Цитата Сообщение от Maluda Посмотреть сообщение
Мне кажется, или у вас позиция лишь бы что-то сказать, но не так как у меня?
Все ясно, больше вопросов не имею. Зря ввязался в эту тему. Вот так и получаются приложения, которые потом невозможно использовать.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 12:16
Я поэтому ему и написал, что необходимо жестко контролировать количество Synchronize и не вызывать каждый раз при малейшем изменении любого из свойств.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.09.2016, 13:19  [ТС]
Maluda, volvo, можно я выскажу свою точку зрения. Сейчас я больше склоняюсь к тому, что шаблон использовать надо. Однако его надо немного дополнить: не устанавливать свойство IsUpdate, если сохраняемые данные те же, что уже сохранены в переменной шаблона.

Склонность к использованию шаблона объясняю следующей причиной. По сути, функция обновления данных, совместно шаблонными переменными, делает то же самое что и код компонента, приведенный Maluda, а именно, он не обновляет данные, если они не изменились. Однако, в силу того, что большинство моих переменных обновляется редко, наверное лучше, чтобы проверка на изменение шла в функции обновления, а не в коде компонента. Думаю, что проверка в шаблонной переменной будет работать намного быстрее, чем проверка в коде компонента. Кроме этого, где уверенность в том, что каждый компонент делает проверку на изменение всех своих свойств при записи в них значений?

P.S. Повторюсь, такое мнение я имею сейчас и, возможно, какие-то доводы и/или примеры меня переубедят.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 14:24
d7d1cd, приведи код функции ReadData

Добавлено через 4 минуты
То есть, мне непонятно, почему в процессе может поменяться длительность ProgressBar, я так понимаю это происходит где-то внутри ReadData
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.09.2016, 14:35  [ТС]
Maluda, а кода то и нет... Я ж просто пример привел. Ведь эта функция не имеет отношения к моему вопросу.

Добавлено через 1 минуту
Длительность ProgressBar поменяться не может. Но сначала она вычисляется в потоке и записывается в свойство ProgressBar.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 14:43
Вот плохо, что всегда приводишь абстрактный код. Так как любой опытный программист сразу замечает кучу важных деталей, например:

C++
1
2
3
while(!Terminated || ReadData() != 0)
  {
   pResult_Caption = L"Прочитано: " + String(ReadData());
Что здесь видим? 2 раза вызывается функция ReadData, которая может выдать абсолютно разные результаты. Плюс вопрос: блокирует она поток или нет?

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

В общем, нужен конкретный код, чтобы вести конкретный разговор.
А самое главное, что ты не понял то, что тебе пытались и я и volvo сказать, это то, что тебе необходимо понять, надо ли тебе вызывать Synchronize или нет. То есть, если ты будешь его 1000 раз в секунду вызывать, ты повесишь программу.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
09.09.2016, 15:06  [ТС]
Цитата Сообщение от Maluda Посмотреть сообщение
Ты хочешь, чтобы тебя похвалили за твой шаблон?
Я не прошу хвалить меня. Я хочу научиться делать правильно, чтобы потом "получались приложения, которые можно использовать".

Цитата Сообщение от Maluda Посмотреть сообщение
Так как там у тебя сплошное копирование, вместо того, чтобы, например, строковые значения передавать по ссылке.
Так покажите как правильно. Опыта маловато. Я даже не вижу где у меня в шаблоне копирование.

Цитата Сообщение от Maluda Посмотреть сообщение
То есть, если ты будешь его 1000 раз в секунду вызывать, ты повесишь программу.
Я согласен, что так часто вызывать обновление не правильно. Но ведь Synchronize выполняет код в главном потоке. Подвисать тогда будет созданный поток.
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
09.09.2016, 16:14
d7d1cd, Насколько вижу тут нужен совсем другой подход. А именно - исключить вызов Synchronize если нет обновления. т.е. завести флаг обновления который устанавливается при записи любого из свойств и сбрасывется при вызове RefreshProgressForm,. Ну
Цитата Сообщение от d7d1cd Посмотреть сообщение
Но ведь Synchronize выполняет код в главном потоке. Подвисать тогда будет созданный поток.
Цитата Сообщение от d7d1cd Посмотреть сообщение
Подвисать тогда будет созданный поток.
Там того кода кот наплакал. Десяток кепшинов установить даже суперкомпутерам 60-х не задача, не то что сегодняшним часам. Если бы от таких действий что то фризилось бы, то оконных фреймверков вообще не существовало бы. А они существуют с 70-х. Основная задержка в моменте синхронизации с главным потоком. Причем не главного потока а того который Synchronize вызывает.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 16:18
Решил привести пример.

ЗАДАЧА: непрерывно (с максимальной частотой) считывать данные автомобиля с ЭБУ, выводить пользователю

Имеется 3 компонента TLabel (скорость, тахометр, текстовое сообщение от ЭБУ).
2 компонента TTrackBar (текущая передача, переключатель трех-позиционный стеклоочистителя)

Данные о скорости, тахометре достаточно показывать с частотой не чаще 16Гц(можно регулировать) , текущую передачу, позиция стеклоочистителя, сообщение ЭБУ будем показывать в любом случае

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
__fastcall CarThread::CarThread(bool CreateSuspended) : TThread(CreateSuspended) {
 
}
 
//---------------------------------------------------------------------------
template<typename T>
void SetValue(T &Source, const T &Val, bool &bChanged) {
    if (Source != Val) {
        Source = Val;
        bChanged = true;
    }
}
 
//---------------------------------------------------------------------------
bool __fastcall CarThread::GetDataFromCar() {
    bool bSomethingChanged = false;
 
    // секция данных, которые очень быстро и часто меняются
    {
        SetValue<int>(FSpeed, Random(160), bSomethingChanged);
        SetValue<int>(FRate, Random(6000), bSomethingChanged);
 
        static int ALastDisplayTime = GetTickCount();
        // если данные изменились, но еще не прошло 60 мсек, то сбрасываем флаг
        if (bSomethingChanged && (GetTickCount() - ALastDisplayTime > 60)) {
            ALastDisplayTime = GetTickCount();
        }
        else {
            bSomethingChanged = false;
        }
    }
 
    // секция данных, которые очень редко меняются
    {
        // сымитируем смену данных раз в секунду и любое изменение будем отображать
        static int iCountRearData = GetTickCount();
        if (GetTickCount() - iCountRearData > 1000) {
 
            SetValue<TCarGear>(FGear, TCarGear(Random(TCarGear::cgThree)), bSomethingChanged);
            SetValue<TCarGlassWiper>(FGlassWiper, TCarGlassWiper(Random(TCarGlassWiper::cgwHigh)), bSomethingChanged);
            SetValue<UnicodeString>(FCarMessage, CarMessages[Random(3)], bSomethingChanged);
 
            iCountRearData = GetTickCount();
        }
    }
 
    return bSomethingChanged;
}
 
//---------------------------------------------------------------------------
void __fastcall CarThread::RefreshData() {
    Form2->LabelSpeed->Caption = UnicodeString().sprintf(L"Текущая скорость=%d", FSpeed);
    Form2->LabelRate->Caption = UnicodeString().sprintf(L"Тахометр=%d", FRate);
    Form2->LabelMessage->Caption = FCarMessage;
 
    Form2->TrackGear->Position = FGear;
    Form2->TrackWiper->Position = FGlassWiper;
}
 
//---------------------------------------------------------------------------
void __fastcall CarThread::Execute() {
    //---- Place thread code here ----
    while (!Terminated) {
        if (GetDataFromCar()) {
            Synchronize(&RefreshData);
        }
        // даём "подышать" приложению
        Sleep(16);
    }
}
//---------------------------------------------------------------------------
0
 Аватар для Fulcrum_013
2083 / 1574 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
09.09.2016, 16:20
А вообще оптимизировать нужно там где нужно а не там где можно выжать сотню-другую тактов экономии раз в час.

Добавлено через 1 минуту
Цитата Сообщение от Maluda Посмотреть сообщение
ЗАДАЧА: непрерывно (с максимальной частотой) считывать данные автомобиля с ЭБУ, выводить пользователю
Ни винде ни билдеру ни одной из осей под которые он компилить обучен в таких задачах не место.
0
 Аватар для Maluda
1280 / 598 / 116
Регистрация: 18.08.2009
Сообщений: 832
09.09.2016, 16:32
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Ни винде ни билдеру ни одной из осей под которые он компилить обучен в таких задачах не место.
Ну, что за глупости. Тебе привести сотню другую программ? (ODIS, VAS-PC)

Кстати, теперь моя очередь поумничать:
C++
1
#define if (a) if( (a) && rand() )
прикол не удастся, так как будет практически всегда rand()==true, возможно даже ни разу не будет false, если не вызывать миллиарды раз
допиши вот так
C++
1
rand()%10
и будет тебе счастье
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.09.2016, 16:32
Помогаю со студенческими работами здесь

VBS: Вывод данных(потока) в другое приложение и запуск с параметрами
Люди добрые, просьба помочь, в VBS я к сожалению полный профан.. Есть VBS скрипт, в который нужно добавить строчку запуска приложения...

Быстрый вывод картинок из БД
такая проблема: Адреса картинок лежат в бд. при показе картинки достается адрес из бд, по нему считывается файл file_get_contents....

Быстрый ввод и вывод
Добрый день. Прошу прощения за нубский вопрос, но все-таки... Хотелось бы узнать у гуру, какие операторы обеспечивают самый быстрой...

Быстрый вывод множества изображений одновременно
У меня есть двумерный массив. Каждому из 5 вариантов элемента массива соответствует своё изображение. Я с помощью обычного цикла...

Быстрый вывод программно созданного изображения
Здравствуйте=)! Программно создаются несколько изображений и хранятся в ОЗУ во время выполнения проги. Картинки порядка 1600Х1200, в виде...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru