我无法生成一个非常简单的示例来开始使用Qt多线程。我阅读了很多帖子和教程,但它仍然没有用。
让后台工作者独立于GUI。哦,哇......
一个简单的例子:
Engine
类QMainWindow
QTimer
但如果您左键单击GUI的标题栏,请按住鼠标按钮(即最小化按钮)计数器将停止!即使它是在非GUI环境中创建的,并且它已在另一个线程中移动了!
的main.cpp
#include "engine.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Engine e;
return a.exec();
}
engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include "mainwindow.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
MainWindow mainWindow;
QThread *thread;
QTimer *timer;
private slots:
void foo();
};
#endif // ENGINE_H
engine.c
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
thread = new QThread(this);
timer = new QTimer();
timer->setInterval(100);
connect(timer, &QTimer::timeout, this, &Engine::foo);
connect(thread, &QThread::started, timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
timer->moveToThread(thread);
thread->start();
mainWindow.show();
}
void Engine::foo()
{
static int i;
qDebug() << ++i;
}
QMainWindow
不包含任何代码。
答案 0 :(得分:5)
基本上,Qt有一个处理GUI的线程(通常是主线程)。 GUI工作将阻止特定于此线程的任何对象。您需要将GUI保留在交互式合作伙伴之外。
更具体地说,您的Engine
对象驻留在GUI /主线程中。即使您的计时器被发送到工作线程,它的信号也会被分派到主线程中的插槽foo()
。
您需要对Engine
和主窗口进行解除处理,使Engine
可以驻留在自己的线程中,并在GUI阻塞时处理信号。
答案 1 :(得分:1)
看起来您将QTimer实例移动到了自定义线程,但是您没有将Engine实例移动到此线程,因此,Engine类的foo槽将在主线程中执行。
我建议您在Engine类中使用额外帮助QObject派生的类实例,并将其移动到Engine构造函数中的新线程。
使用以下更改解决方案即使按下最小化按钮也能正常工作(我已经评论了我添加或更改任何内容的位置。还添加了新的QObject派生类 EngineWorker ):
Engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include "mainwindow.h"
#include "engineworker.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
MainWindow mainWindow;
QThread *thread;
QTimer *timer;
//additional QObject-derived class
EngineWorker *worker;
private slots:
void foo();
};
#endif // ENGINE_H
Engine.cpp
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
thread = new QThread(this);
timer = new QTimer();
//Creating instance of Engine worker
worker = new EngineWorker();
timer->setInterval(100);
//Connecting Engine worker' foo slot to timer
connect(timer, &QTimer::timeout, worker, &EngineWorker::foo);
connect(thread, &QThread::started, timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
timer->moveToThread(thread);
//Moving worker to custom thread
worker->moveToThread(thread);
thread->start();
mainWindow.show();
}
void Engine::foo()
{
static int i;
qDebug() << ++i;
}
EngineWorker.h
#ifndef ENGINEWORKER_H
#define ENGINEWORKER_H
#include <QObject>
#include <QDebug>
class EngineWorker : public QObject
{
Q_OBJECT
public:
explicit EngineWorker(QObject *parent = 0);
signals:
public slots:
void foo();
};
#endif // ENGINEWORKER_H
EngineWorker.cpp
#include "engineworker.h"
EngineWorker::EngineWorker(QObject *parent) : QObject(parent)
{
}
//foo slot of EngineWorker class
void EngineWorker::foo()
{
static int j;
qDebug() <<"Worker: "<< ++j;
}