Имеется объект, который живёт в другом потоке и выполняет различные задачи по запросам или выполняет повторяющиеся задачи.
Более приземленное описание. Через протокол modbus RTU опрашиваются датчики. Датчиков 247 штук. Используются 3 команды, чтение регистров, запись регистров, чтение ID. Управление датчиками может быть ручное или автоматическое. При ручном режиме принимаем данные из главного потока и передаем на датчик, после ответа датчика передаем данные в главный поток для записи в usb устройство и отображение на экране. При автоматическом режиме управляем датчиками по заданному алгоритму и отсылаем ответы датчиков в главный поток для записи на usb устройство и отображения данных.
Вот не знаю как лучше реализовать это.
Можно написать реализацию шаблона проектирования event loop, который будет асинхронно запускать выполнение задач в QThreadPool и ожидать их завершения. В данном примере, взятом из этого репозитория, цикл событий обрабатывает события Await, при поступлении которого изымается Monitor, который, если не завершен, пробрасывается обернутым Await-ом в цикл событий по-новой.
class Engine : public QThread {
Q_OBJECT
private:
QStack<Monitor*>* rethrow;
QThreadPool* pool;
public:
explicit Engine() : QThread(nullptr) {
qDebug() << "Engine ctor thread: " << QThread::currentThreadId();
moveToThread(this);
}
virtual ~Engine(){
qDebug() << "Engine dtor";
}
protected:
virtual void run(){
qDebug() << "Engine thread" <<QThread::currentThreadId();
pool = new QThreadPool(this);
rethrow = new QStack<Monitor*>();
pool -> setMaxThreadCount(QThread::idealThreadCount());
QEventLoop loop;
connect(qApp,SIGNAL(aboutToQuit()),&loop,SLOT(quit()));
qDebug() << "Engine event loop started";
while(true) {
if(!loop.processEvents()) {
if (qApp->closingDown()) {
terminate();
} else {
bool continueLoop = rethrow->isEmpty();
while(continueLoop) {
QCoreApplication::postEvent (
this,
new Await(rethrow->pop())
);
continueLoop = rethrow->isEmpty();
QThread::msleep(250);
}
}
}
}
qDebug() << "Engine event loop exit";
pool->deleteLater();
delete rethrow;
emit done();
}
virtual bool event(QEvent *event){
if (qApp->closingDown()) {
return QObject::event(e);
} else if (e->type() == Event::staticType()) {
Event* event = static_cast<Event*>(e);
switch(event->process(this,pool)){
case EventResult::AwaiterRethrow:
rethrow->push(static_cast<Await*>(e)->getMonitor());
return true;
default:
return true;
}
} else {
return QObject::event(e);
}
}
signals:
void done();
};
...
class Monitor : public QObject {
Q_OBJECT
public:
explicit Monitor();
virtual ~Monitor();
virtual bool isStarted() = 0;
virtual bool isCanceled() = 0;
virtual bool isFinished() = 0;
virtual void start(
QThreadPool* pool,
QObject* engine
) = 0;
};
...
class Await : public Event {
private:
Monitor* monitor;
public:
Await(Monitor* monitor);
virtual ~Await();
Monitor* getMonitor() const;
virtual EventResult process(
QObject *engine,
QThreadPool *pool
) {
if(monitor->isCanceled() || monitor->isFinished()) {
qDebug() << "Awaiter monitor cleanup";
delete monitor;
return EventResult::Ok;
} else {
if(!monitor->isStarted()){
qDebug() << "Awaiter monitor init";
monitor->start(pool, engine);
}
qDebug() << "Awaiter monitor skip";
return EventResult::AwaiterRethrow;
}
}
};
...
enum EventResult {
AwaiterRethrow,
Ok,
};
...
class Event : public QEvent {
public:
explicit Event();
virtual ~Event();
virtual EventResult process(
QObject* engine,
QThreadPool* pool
) = 0;
static QEvent::Type staticType();
};
...
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Engine e;
e.start();
QJSValue callback = ...
Monitors::TimerMonitor* monitor = new Monitors::TimerMonitor(
callback,
1000
);
QCoreApplication::postEvent(&e, new Events::Await(monitor));
QObject::connect(&e, SIGNAL(done()), qApp, SLOT(quit()));
return app.exec();
}
Просмотрите документацию и попробуйте запустить, богатый файловый лог позволяет понять, что происходит под капотом. В случае с этим приложением происходит ожидание событий таймера.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Как называется элемент интерфейса пользователя, который позволяет выбрать путь к файлу или директорию? Такой же элемент, который при установке...
Нужно проверить на четность строку типа wchar_t и добавить в конце символ если она не четнаяНо при работе выдает, что размерность буферного массива...
класс TreeNode наследуется от CalcTree, в классе CalcTree создается указатель на TreeNode => вызывается конструктор TreeNode, который рекурсивно вызывает конструктор...
Как с помощью функции GetPixel получить данные о пикселе файла изображения? Или как сделать хендл не к окну консоли, а к файлу?