如何在QThread中运行定时器? [英] How to run a timer inside a QThread?

查看:1738
本文介绍了如何在QThread中运行定时器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在QThread中运行一个计时器。我写了一些代码,我在运行时得到一些错误。请引导我走正确的方向。

 (Parent是QThread(0x1498d10),父级的线程是QThread(0x11272b0),当前线程是QThread (0x1498d10)

mainwindow.h // main .h文件

  #ifndef MAINWINDOW_H 
#define MAINWINDOW_H

#include< QMainWindow>
#includemythread.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

mainwindow.cpp // main .cpp file

  #includemainwindow.h
#includeui_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;
}



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

mythread.cpp

  #includemythread.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;
}


解决方案

意见 - 不要子类化 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;

};

实施

  #includemyclass.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:<计数;
if(m_wantToSleep)
sleep(1);
}

我们有工作的代码。



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

  #includemainwindow.h
#includeui_mainwindow.h

#include< QThread>

MainWindow :: MainWindow(QWidget * parent):
QMainWindow(parent),
ui(new Ui :: MainWindow)
{
ui- > setupUi(this);
QThread * thread1 = new QThread; //第一个线程
QThread * thread2 = new QThread; // Second thread

thread1-> start();
thread2-> start();

MyClass * myClass = new MyClass(false,standard class);
MyClass * mySleepClass = new MyClass(true,sleeper class);

//更好地实现开始时间段启动计时器(未实现)
// connect(thread1,SIGNAL(started),myClass,SLOT(start()))
//但这足够了,因为在类被移动到另一个thred之后计时器将发出第一个信号
// mySleepClass-> moveToThread(thread1);
// myClass-> moveToThread(thread1);
}

MainWindow ::〜MainWindow()
{
delete ui;
}

现在我们可以玩线程: p>

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



使用新线程。对象在当前线程,这就是为什么GUI将被阻止。 (因为我在一个实例中使用睡眠函数)

  // mySleepClass-> moveToThread(thread1); 
// myClass-> moveToThread(thread1);

无阻止GUI


$ b b

我们还有两个线程运行。为什么不使用它们。在例子QThreads已经运行,但他们玩什么。



魔法函数是moveToThread



取消注释行,您可以看到,该GUI不会被阻止。两个实例都在新线程中。但是,再一次,有一个睡眠功能,所以一个应该计数比其他更快。但它不是。因为他们互相阻挡。它们在一个线程中。

  mySleepClass-> moveToThread(thread1); 
myClass-> moveToThread(thread1);

以上两种情况下的结果应该是:(实例存在于同一个线程中并共享相同的事件循环,因此他们彼此阻止)

 正常类count:1 
sleeper classcount:1
normal classcount:2
sleeper classcount:2
normal classcount:3
sleeper classcount:3



因此将它们移动到单独的线程



现在GUI没有被阻止,更靠近的实例彼此。

  mySleepClass-> moveToThread(thread1); 
myClass-> moveToThread(thread2);

结果应该是:(且不应阻止GUI)

 sleeper classcount:1 
normal classcount:1
normal classcount:2
normal classcount:3
normal classcount:4
normal classcount:5


b $ b

希望可以理解。对我来说,这是更逻辑的aproach然后继子类。



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



对于任何不同意的人,我只是想说: MyClass是线程支持的计数器听起来更好: MyClass是thread与反作用:)


I would like to run a timer inside a QThread. I have written some code in which i am getting some error during the run time. Please guide me into the right direction. What am I doing wrong?

(Parent is QThread(0x1498d10), parent's thread is QThread(0x11272b0), current thread is QThread(0x1498d10)

mainwindow.h //main .h file

#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

mainwindow.cpp //main .cpp file

#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;
}

mythread.h // class for thread

#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

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;
}

解决方案

Just my humble opinion - Do not to subclass QThread anymore, when you do not need to.

I think, you just want to run your class in new thread or more probably you do not want to block other tasks. Your class is not thread itself. Subclassing basically means that your class IS what you are subclassing.

In other words: Let QThread do its job and concentrate on your class to do what it should do.

Example: MyClass itself does not know anything about threads. It just do what it has to do. Incrementing value and showing results ( plus some sleep part to show how it can block other functions or gui )

Header file

#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;

};

Implementation

#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);
}

We have code which does the job.

Now implement more threads - its very simple ( memory management, etc not handled to have simple example )

#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;
}

Now we can play with threads:

Blocking GUI ( of course we do not want this )

Initial example works without using new threads. Objects are in current thread and that's why GUI will be blocked. ( since I use sleep function in one instance )

//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);

Non blocking GUI

We have two more threads running. Why not to use them. In example QThreads are already running, but they play with nothing. Let's move our instances there, to ensure main loop, where GUI is living will not be blocked anymore.

Magic function is moveToThread

Uncomment lines and you can see, that GUI will not be blocked. Both instances are in new thread. But then again, there is a sleep function so One should be counting faster then other. But it is not. Because they are blocking each other. They are in one thread.

mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread1);

Results in both previous cases should be: ( instances lives in same thread and shares the same event loop, so they are blocking each other )

"normal class"  count:  1 
"sleeper class"  count:  1 
"normal class"  count:  2 
"sleeper class"  count:  2 
"normal class"  count:  3 
"sleeper class"  count:  3 

So move them to separate thread

Now GUI is not blocked, niether instances each other.

mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread2);

Results should be: ( and GUI should not be blocked )

"sleeper class"  count:  1 
"normal class"  count:  1 
"normal class"  count:  2 
"normal class"  count:  3 
"normal class"  count:  4 
"normal class"  count:  5 

Hope It was understandable. As for me, this is more logic aproach then subclassing.

Of course you can create QThread in your MyClass, it is not necessary to create it oustide MyClass, I just wanted to show, that you can create one thread and move there more instances.

For anyone who disagree, I just wanted to say that: MyClass is counter with thread support sounds better then: MyClass is thread with counter ability :)

这篇关于如何在QThread中运行定时器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆