Russian Qt Forum
Март 29, 2024, 11:40
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
Периодическая обработка данных из другого потока
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Периодическая обработка данных из другого потока (Прочитано 3755 раз)
CountZero
Гость
Периодическая обработка данных из другого потока
«
:
Март 16, 2017, 14:27 »
Добрый день.
Имеется следующая задача: из основного потока программы запускаются два потока.
Первый поток в бесконечном цикле получает осуществляет запросы к внешнему устройству, получает от него данные, обрабатывает их и генерирует сигнал о том, что новые данные пришли. Второй поток должен получить данные из первого потока, выдать управляющий сигнал, и после этого выдача управляющих сигналов должна быть заблокирована на некоторое время, в зависимости от результатов обработки данных от первого потока. Собственно вопрос по реализации этой самой блокировки как ее сделать?
Для экспериментов накидал следующий код:
1. Поток имитирующий получение данных от устройства.
Код:
MainThread::MainThread()
{
run=true;
tmr = new QTime;
}
void MainThread::process()
{
double PVSim;
tmr->start();
while (run)
{
PVSim = 2+sin(tmr->elapsed());
emit SendData(PVSim);
Sleep(100);
}
emit finished();
}
void MainThread::stop()
{
run=false;
}
2. Поток имитирующий управляющий:
Код:
ControlThread::ControlThread()
{
}
void ControlThread::process()
{
percent = PV * 100 / 2;
emit AutoFirst(percent,1,1);
}
void ControlThread::stop()
{
emit finished();
}
void ControlThread::GetPV(double data)
{
PV = data;
process();
}
3. Создание потока, настройка сигналов, слотов в основном:
Код:
threadControl = new QThread;
threadMain = new QThread;
Main = new MainThread;
Control = new ControlThread(1,16,12);
Main->moveToThread(threadMain);
Control->moveToThread(threadControl);
connect(threadControl, SIGNAL(started()), Control, SLOT(process()));
connect(Control, SIGNAL(finished()), threadControl, SLOT(quit()));
connect(Control, SIGNAL(finished()), Control, SLOT(deleteLater()));
connect(threadControl, SIGNAL(finished()), threadControl, SLOT(deleteLater()));
connect(this,SIGNAL(SetSP(double)),Control,SLOT(GetSP(double)));
connect(Control,SIGNAL(AutoFirst(int,int,int)),this,SLOT(Auto(int,int,int)));
connect(threadMain, SIGNAL(started()), Main, SLOT(process()));
connect(Main, SIGNAL(finished()), threadMain, SLOT(quit()));
connect(Main, SIGNAL(finished()), Main, SLOT(deleteLater()));
connect(threadMain, SIGNAL(finished()), threadMain, SLOT(deleteLater()));
connect(Main,SIGNAL(SendData(double)),Control,SLOT(GetPV(double)));
В такой реализации у нас "управляющий" поток выдает сигналы с частотой опроса устройства - данные пришли, сигнал выдали. А требуется чтобы он на основании данных выдал сигнал, потом X секунд подождал (данные при этом можно обновлять, реакция не требуется), а через Х секунд началась новая итерация.
Пробовал вариант со Sleep, но он естественно просто замораживает отработку, а сигналы приходят и после "разморозки" начинается отработка каждого блока из пришедших данных, а нужно отработать только по последним данным.
Записан
__Heaven__
Джедай : наставник для всех
Offline
Сообщений: 2130
Re: Периодическая обработка данных из другого потока
«
Ответ #1 :
Март 17, 2017, 09:32 »
Не сильно разбирался в Вашем коде, но, кажется, вам должен подойти таймер, генерирующий сигналы на таймауте.
http://doc.qt.io/qt-5/qtimer.html#timeout
Возможно будет достаточным заменить бесконечный цикл на него.
Записан
CountZero
Гость
Re: Периодическая обработка данных из другого потока
«
Ответ #2 :
Март 17, 2017, 10:04 »
Цитата: __Heaven__ от Март 17, 2017, 09:32
Не сильно разбирался в Вашем коде, но, кажется, вам должен подойти таймер, генерирующий сигналы на таймауте.
http://doc.qt.io/qt-5/qtimer.html#timeout
Возможно будет достаточным заменить бесконечный цикл на него.
Проблем с бесконечным циклом как раз нет, и его менять не надо. Суть как раз в том, что данные приходят и должны приходить с частотой большей чем частота реакции на данные. Менять надо было поведение второго потока, в котором цикла нет. Про QTimer и его timeout() естественно знаю, вопрос был как корректно организовать взаимодействие.
Проблему уже решил самостоятельно. На самом деле все оказалось настолько очевидным, что даже странно, что сразу не пришло в голову. В следующем сообщении опишу решение.
Записан
CountZero
Гость
Re: Периодическая обработка данных из другого потока
«
Ответ #3 :
Март 17, 2017, 10:47 »
Проблема решена.
Для того чтобы решить задачу требуется добавить таймер в MainWindow, который и будет периодически запускать отработку второго процесса.
В MainWindow:
1. Добавляем QTimer* tmr.
2. Добавляем в MainWindow слот SetTimer(int tm) в котором будем запускать таймер необходимой задержки командой tmr->start(tm);
3. Соединяем сигнал таймера tmr->timeout() со слотом process() второго процесса
4. Cоединяем сигнал delay(int tm) второго процесса со слотом SetTimer(int tm)
В ControlThread:
1. Добавляем сигнал delay(int tm),
2. Убираем запуск process() из getPV(double data)
3. Добавляем в конце выполнения всей логики process() выработку сигнала delay(miliseconds)
У нас получается этакое кольцо - таймер запускает process, process запускает таймер, для начального входа в этот цикл используется сигнал от нити started(), который запустит process() первый раз, чтобы все было нормально в конструкторе следует проинициализировать данные таким образом чтобы первый прогон process() без полученных данных отработал корректно.
Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
setupUi(this);
threadControl = new QThread;
threadMain = new QThread;
Main = new MainThread;
Control = new ControlThread(1,16,12);
Main->moveToThread(threadMain);
Control->moveToThread(threadControl);
connect(threadControl, SIGNAL(started()), Control, SLOT(process()));
connect(Control, SIGNAL(finished()), threadControl, SLOT(quit()));
connect(Control, SIGNAL(finished()), Control, SLOT(deleteLater()));
connect(threadControl, SIGNAL(finished()), threadControl, SLOT(deleteLater()));
connect(this,SIGNAL(SetSP(double)),Control,SLOT(GetSP(double)));
connect(Control,SIGNAL(AutoFirst(int,int,int)),this,SLOT(Auto(int,int,int)));
connect(threadMain, SIGNAL(started()), Main, SLOT(process()));
connect(Main, SIGNAL(finished()), threadMain, SLOT(quit()));
connect(Main, SIGNAL(finished()), Main, SLOT(deleteLater()));
connect(threadMain, SIGNAL(finished()), threadMain, SLOT(deleteLater()));
connect(Main,SIGNAL(SendData(double,int)),Control,SLOT(GetPV(double,int)));
threadControl->start();
threadMain->start();
tmr = new QTimer;
connect(tmr,SIGNAL(timeout()),Control,SLOT(process()));
connect(Control,SIGNAL(delay(int)),this,SLOT(setTimer(int)));
}
void MainWindow::setTimer(int tm)
{
tmr->start(tm);
}
Код:
void ControlThread::process()
{
percent = SensPV * 100 / 2;
emit delay(miliseconds);
}
void ControlThread::GetPV(double data)
{
SensPV = data;
}
Записан
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...