如何在QThread中运行计时器?

Rsv*_*vay 4 c++ qt qt-creator qthread qtimer

我想在QThread中运行一个计时器.我写了一些代码,其中我在运行时遇到了一些错误.请引导我走向正确的方向.我究竟做错了什么?

(Parent is QThread(0x1498d10), parent's thread is QThread(0x11272b0), current thread is QThread(0x1498d10)
Run Code Online (Sandbox Code Playgroud)

mainwindow.h //主.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "mythread.h"
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    MyThread *myt;

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
Run Code Online (Sandbox Code Playgroud)

mainwindow.cpp //主.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    myt=new MyThread();
    myt->start();
    MainWindow w;
}

MainWindow::~MainWindow()
{
    delete ui;
}
Run Code Online (Sandbox Code Playgroud)

mythread.h //线程类

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTimer>
class MyThread:public QThread
{
public:
    MyThread();
    void run();
   QTimer *thr;
public slots:
   void slo();
};

#endif // MYTHREAD_H
Run Code Online (Sandbox Code Playgroud)

mythread.cpp

#include "mythread.h"

MyThread::MyThread()
{
    thr= new QTimer();
    connect(thr,SIGNAL(timeout()),this,SLOT(slo()));
}
 void MyThread::run()
 {
    thr->start(1000);
 }
void MyThread::slo()
{
    int i,j=0;
    i=i+j;
}
Run Code Online (Sandbox Code Playgroud)

fbu*_*cek 8

只是我的拙见 - 当你不需要时,不要再继承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;

};
Run Code Online (Sandbox Code Playgroud)

履行

#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);
}
Run Code Online (Sandbox Code Playgroud)

我们有代码来完成这项工作.

现在实现更多的线程 - 它非常简单(内存管理等没有处理,只有简单的例子)

#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;
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以玩线程了:

阻止GUI(当然我们不希望这样)

初始示例无需使用新线程即可运行.对象在当前线程中,这就是GUI被阻止的原因.(因为我在一个实例中使用sleep函数)

//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
Run Code Online (Sandbox Code Playgroud)

非阻塞GUI

我们还有两个线程在运行.为什么不使用它们.在示例中,QThreads已经在运行,但它们什么都不玩.让我们在那里移动我们的实例,以确保主循环,GUI生存的地方将不再被阻止.

魔术功能是moveToThread

取消注释行,您可以看到,GUI不会被阻止.两个实例都在新线程中.但话说回来,有一个睡眠功能,所以一个应该比其他更快.但事实并非如此.因为他们互相阻挡.他们在一个线程中.

mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread1);
Run Code Online (Sandbox Code Playgroud)

以前两种情况的结果应该是:(实例位于同一个线程中并共享相同的事件循环,因此它们相互阻塞)

"normal class"  count:  1 
"sleeper class"  count:  1 
"normal class"  count:  2 
"sleeper class"  count:  2 
"normal class"  count:  3 
"sleeper class"  count:  3 
Run Code Online (Sandbox Code Playgroud)

所以将它们移到单独的线程

现在GUI没有被阻止,彼此没有实例.

mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread2);
Run Code Online (Sandbox Code Playgroud)

结果应该是:(不应阻止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 
Run Code Online (Sandbox Code Playgroud)

希望这是可以理解的.至于我,这是更多的逻辑方法然后继承.

当然你可以在你的MyClass中创建QThread,没有必要创建它oustide MyClass,我只是想表明,你可以创建一个线程并移动更多的实例.

对于任何不同意的人,我只是想说:MyClass是反线程支持听起来更好的话:MyClass是具有反击能力的线程 :)


Dmi*_*nov 6

您的计时器不属于您的主题.您应该在run()方法中创建它,或者在将它连接到插槽之前调用tmer-> moveToThread,但是在线程启动之后.

检查一下:MyThread属于你的主线程.你在MyThread的构造函数中创建计时器 - 所以计时器也属于主线程.但是你试图在:: run方法中初始化并使用它,它属于其他线程.