我有一个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()
插槽仅在工作完成后才开始调用。
答案 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)