1

我有一个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()工作完成后才开始被调用。

4

2 回答 2

2

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

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

或者,您可以使用不同的线程来执行这些估计。如果它们的性能不太密集,您甚至可以使用 GUI/主线程。GUI/主线程应保持对事件的“响应”(否则应用程序似乎挂起),因此它可以timeout及时处理事件。

于 2014-05-12T11:35:43.383 回答
-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

于 2014-05-12T13:34:29.090 回答