创建Qt线程事件循环。

6

我正在使用Qt编写GUI应用程序。

主线程负责GUI并创建QThread以便与对象一起执行一些工作。

class Worker
{
    void start() {
        QTimer* timer = new Timer();
        connect(timer,SIGNAL(timeout()),this,SLOT(do()));
    }

    void do() {
        //do some stuff
        emit finished();
    }
}



class GUI
{
    //do some GUI work then call startWorker();

    void startWorker() {
        QThread* thread = new Thread();
        Worker* worker = new Worker();

        worker->moveToThread(thread);

        connect(thread, SIGNAL(started()), worker, SLOT(start()));
        connect(worker, SIGNAL(finished()), workerthread, SLOT(quit()));
        connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    }
}

现在我有几个问题:
  1. The timer in my worker class does not work. Maybe it is because the new thread has no event loop, but I have no idea how to create such one. I tried

    connect(workerthread, SIGNAL(started()), workerthread, SLOT(exec()));

    but it does not work either.

  2. When I try to wait on the new thread, the signal is never sent

    class GUI
    {
        void exit() {
            thread->wait();
        }
    }
    

我认为这也是因为没有事件循环,因此没有信号被发出。

有人有解决这些问题的想法吗?


你是否忘记在线程上调用start方法?这并未在你的代码示例中出现。 - cgmb
2个回答

2

为什么不使用Qt线程池呢?这样你可以让你的任务类继承自QRunnable和QObject,这样就可以使用信号和槽来在不同的线程之间传递数据,实现起来更加简单,并且可以提高性能,因为不需要每次重新创建线程或者让一个线程一直处于休眠状态。

class myTask : public QObject, public QRunnable{
Q_OBJECT

protected:
void run(); //where you actually implement what is supposed to do

signals:
void done(int data);//change int to whatever data type you need

}

//moc click example, or use a timer to call this function every x amount of time
void button_click(){
   myTask *task = new myTask();
   task->setAutoDelete(true);
   connect(task,SIGNAL(done(int)),this,SLOT(after_done(int)),Qt::QueuedConnection);
   QThreadPool::globalInstance()->start(task);
}

默认情况下,你的应用程序会自动获取1个线程,你可以使用它来处理图形,然后使用qthreadpool按需处理数据/对象,甚至可以设置应用程序可用于处理新请求的最大线程数,其余线程将保留在队列中,直到有一个线程被释放。

QThreadPool::globalInstance()->setMaxThreadCount(5);

谢谢,这是一个非常简单的解决方案,我将在未来使用它。但现在我决定使用另一种解决方案来解决我的当前问题,因为我想在另一个线程中执行一些频繁的工作。现在我的解决方案是实现一个自己的线程,并使用exec()在其中拥有一个事件循环。 - Sven Jung
听起来不错,我还想让你注意到它使用了第二个线程(在我的情况下最多同时使用5个线程),一旦任务完成,线程不会被销毁,而是被重用,在所有线程都很昂贵的情况下增加性能。无论如何,很高兴能帮助。 - LemonCool

2

这是一个示例代码:

QThread* thread = new QThread();
Worker* worker = new Worker(3000);
worker->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(start()));
thread->start();`

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(qint32,QObject *parent = 0);
    qint32 myTime;

signals:
    void   workFinished();

public slots:
    void doWork();
    void start();
    private:
    QTimer *timer;
};


#include "worker.h"
#include <QTimer>
#include <QDebug>
Worker::Worker(qint32 t,QObject *parent) :
    QObject(parent)
{
    myTime=t;
}

void Worker::start()
{
    timer = new QTimer();
    timer->start(myTime);
    qDebug()<<QString("start work in time:%1").arg(myTime);
    connect(timer,SIGNAL(timeout()),this,SLOT(doWork()));
}

void Worker::doWork()
{
    qDebug()<<"dowork";
    timer->stop();
    emit workFinished();
}

调试结果:

开始工作时间:3000

希望这可以帮助您。


是的,它可以工作,但现在我决定使用另一种解决方案。我现在正在使用自己实现的线程。 - Sven Jung
@SvenJung 这是采纳的答案吗?我需要声望,如果是的话,请设置它。 - Jack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接