只是我的拙见—— 当你不需要的时候,不要再继承 QThread了。
我认为,您只想在新线程中运行您的课程,或者更可能您不想阻止其他任务。你的类不是线程本身。子类化基本上意味着您的类就是您的子类化。
换句话说:让 QThread 完成它的工作,并专注于你的班级去做它应该做的事情。
示例: 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 start slot to start timer ( not implemented )
// connect(thread1, SIGNAL(started), myClass, SLOT(start()));
// but this suffice, because timer will emit first signal after class is moved to another thred
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
}
MainWindow::~MainWindow()
{
delete ui;
}
现在我们可以玩线程了:
阻塞 GUI(当然我们不想要这个)
初始示例无需使用新线程即可工作。对象在当前线程中,这就是 GUI 将被阻止的原因。(因为我在一个实例中使用了睡眠功能)
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
非阻塞图形用户界面
我们还有两个线程在运行。为什么不使用它们。在示例中,QThreads 已经在运行,但它们什么也没玩。让我们将实例移到那里,以确保 GUI 所在的主循环不会再被阻塞。
魔术函数是moveToThread
取消注释行,您可以看到,该 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 是具有计数器能力的线程:)