工作线程中的QTimer

时间:2014-05-12 11:04:35

标签: c++ multithreading qt qtimer

我有一个Worker类,它在另一个线程中工作,使用moveToThread()放置它。在Worker::doWork()方法内部,我还创建了一个QTimer,它应该根据任务的估计时间来发布进度更新。

以下是一个例子:

ThreadController::ThreadController()
{
    Worker* worker = new Worker;
    worker->moveToThread(&m_workerThread);

    // ...        

    m_workerThread.start();
    emit startWorker(params); // connected to Worker::doWork()
}


class Worker : public QObject
{
    Q_OBJECT

public slots:
    Worker::doWork(const QString& params)
    {
        QTimer* timer = new QTimer(this);
        connect( timer, SIGNAL(timeout)), this, SLOT(updateProgress()) );
        timer->start(estimateTaskLength() / 100);

        // perform work...
    }
}

现在这不按预期工作。 updateProgress()插槽仅在工作完成后才开始调用。

2 个答案:

答案 0 :(得分:1)

当计时器到期时,timeout事件将排队到您的工作人员QThread的事件队列。但是,您的工作人员QThread正忙于执行doWork(),因此无法处理该事件。一旦线程完成doWork,控制就会返回QThread的事件循环并执行timeout事件。

解决此问题的最简单方法是在QCoreApplication::processEvents()执行期间以特定间隔使用doWork()手动调用事件循环。这将允许QThread更早地执行timeout事件。

或者,您可以使用其他线程来执行这些估算。如果它们不是太强大的性能,你甚至可以使用GUI /主线程。 GUI /主线程应该保持对事件的“响应”(否则应用程序似乎挂起),以便它可以及时处理timeout事件。

答案 1 :(得分:-1)

这可能取决于Qtimer :: timeout与this :: updateProgress之间的连接类型。

默认情况下,它是一个Qt :: AutoConnection,这意味着超时信号将排队,直到接收对象准备好处理它。即doWork完成后。

如果使用

连接
connect( timer, SIGNAL(timeout)), this, SLOT(updateProgress()), Qt::DirectConnection );

应立即处理超时信号。 (确保包含必要的互斥锁和内容,因为这是典型的情况,例如并发访问可能发生..)

http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum