只是我的拙见:不要子类化 QThread当你不需要的时候就不再这样做了。
我认为您只想在新线程中运行您的类,或更可能您不想阻止其他任务。你的类不是线程本身。子类化基本上意味着你的类is你正在子类化什么。
换句话说:让 QThread 做好它的工作,集中精力让你的类做它应该做的事情。
Example:MyClass 本身对线程一无所知。它只是做它必须做的事情。增加一个值并显示结果(加上一些睡眠部分以显示它如何阻止其他功能或 GUI)
头文件
#include <QTimer>
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(bool willSleep, QString name, QObject *parent = 0);
public slots:
void updateCount();
private:
QTimer *timer;
int count;
bool m_wantToSleep;
};
执行
#include "myclass.h"
#include <QDebug>
MyClass::MyClass(bool wantToSleep, QString name, QObject *parent) :
QObject(parent)
{
this->setObjectName(name);
m_wantToSleep = wantToSleep;
count = 0;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateCount()));
timer->start(100);
}
void MyClass::updateCount()
{
++count;
qDebug() << objectName() << " count: " << count;
if (m_wantToSleep)
sleep(1);
}
我们有可以完成这项工作的代码。
现在实现更多线程。非常简单(内存管理等就不处理了,有一个简单的例子)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread *thread1 = new QThread; // First thread
QThread *thread2 = new QThread; // Second thread
thread1->start();
thread2->start();
MyClass *myClass = new MyClass(false, "normal class");
MyClass *mySleepClass = new MyClass(true, "sleeper class");
// Better to implement a start slot to start the timer (not implemented)
// connect(thread1, SIGNAL(started), myClass, SLOT(start()));
// but this suffices, because the timer will emit the first signal after the class is moved to another thread
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
}
MainWindow::~MainWindow()
{
delete ui;
}
现在我们可以使用线程了:
阻止 GUI(当然我们不希望这样)
最初的示例无需使用新线程即可工作。对象位于当前线程中,这就是 GUI 被阻塞的原因(因为我在一个实例中使用了 sleep 函数)。
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
非阻塞图形用户界面
我们还有两个线程正在运行。为什么不使用它们呢?在示例中,QThreads 已经在运行,但它们什么也没玩。让我们将实例移到那里,以确保 GUI 所在的主循环不会再被阻塞。
神奇的功能是移动到线程
取消注释行,您可以看到 GUI 不会被阻止。两个实例都在新线程中。但话又说回来,有一个睡眠功能,所以一个人应该比另一个人计数得更快。但事实并非如此。因为他们互相阻碍。它们在同一个线程中。
mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread1);
前面两种情况的结果应该是:(实例位于同一线程中并共享相同的事件循环,因此它们相互阻塞)
"normal class" count: 1
"sleeper class" count: 1
"normal class" count: 2
"sleeper class" count: 2
"normal class" count: 3
"sleeper class" count: 3
所以将它们移动到一个单独的线程
现在 GUI 不再被阻止;两者都不是彼此的实例。
mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread2);
结果应该是(并且 GUI 不应该被阻止):
"sleeper class" count: 1
"normal class" count: 1
"normal class" count: 2
"normal class" count: 3
"normal class" count: 4
"normal class" count: 5
我希望这是可以理解的。对我来说,这是比子类化更合乎逻辑的方法。
当然你可以在你的MyClass中创建一个QThread实例。没有必要在 MyClass 之外创建它,我只是想表明您可以创建一个线程并在那里移动更多实例。
对于那些不同意的人,我只想说:MyClass 是一个支持线程的计数器听起来比:MyClass是一个具有计数器能力的线程 :)