【发布时间】:2020-04-24 23:47:48
【问题描述】:
QThread 文档提出了两种让代码在单独线程中运行的方法。如果我继承 QThread 并重新实现 run(),那么我会得到 p>
QBasicTimer::start: Timers cannot be started from another thread
-
#include <QWidget>
#include <QThread>
#include <QBasicTimer>
#include <QDebug>
#include <QEvent>
#include <QCoreApplication>
class Worker : public QThread
{
Q_OBJECT
int id;
bool m_abort = false;
bool compute = false;
public:
Worker() {}
protected:
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == id) {
compute = true;
} else {
QObject::timerEvent(event);
}
}
public slots:
void abort() {m_abort = true;}
void run() {
qDebug() << QThread::currentThreadId();
QBasicTimer timer;
id = timer.timerId();
timer.start(1000, this);
forever {
if (m_abort) break;
QCoreApplication::processEvents();
if (compute)
qDebug() << "computed";
compute = false;
}
}
};
class MainWidget : public QWidget
{
Q_OBJECT
QThread thread;
Worker* worker;
public:
MainWidget()
{
qDebug() << QThread::currentThreadId();
worker = new Worker;
worker->start();
}
~MainWidget(){worker->abort();}
};
1) 定时器是从另一个线程启动的吗?
2) 为什么当 QBasicTimer 被 QTimer 替换时我没有收到该警告?
3) 为什么我在使用 moveToThread 时没有收到该警告?
#include <QWidget>
#include <QThread>
#include <QBasicTimer>
#include <QDebug>
#include <QEvent>
#include <QCoreApplication>
class Worker : public QObject
{
Q_OBJECT
QBasicTimer* timer;
bool m_abort = false;
bool compute = false;
public:
Worker() {}
protected:
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == timer->timerId()) {
compute = true;
} else {
QObject::timerEvent(event);
}
}
public slots:
void abort() {m_abort = true;}
void run() {
timer = new QBasicTimer;
timer->start(1000, this);
forever {
if (m_abort) break;
QCoreApplication::processEvents();
if (compute)
qDebug() << "computed";
compute = false;
}
}
};
class MainWidget : public QWidget
{
Q_OBJECT
QThread thread;
Worker* worker;
public:
MainWidget()
{
worker = new Worker;
worker->moveToThread(&thread);
connect(this, &MainWidget::start, worker, &Worker::run);
thread.start();
emit start();
}
~MainWidget(){worker->abort(); thread.quit(); thread.wait();}
signals:
void start();
};
【问题讨论】:
-
你构造了没有父级的计时器,所以当worker移动到它的线程时它不会被移动。
-
你是说 QBasicTimer 计时器?请问我应该如何构建它?
-
@TobySpeight 我不这么认为,计时器是在
run()函数的开头创建并在结尾销毁的。所以当moveToThread()被调用时它甚至不存在。我认为问题在于,不可能从另一个线程捕获定时器的超时,而不是从它启动的线程(停止它也是一样)。 -
@KcFnMi 在您的 moveToThread 示例中,
run()函数创建了一个计时器,启动它并在之后立即退出(顺便说一句,这将破坏计时器)。 -
此外,要在另一个线程中启动计时器,您还需要在相应线程上执行事件循环,否则您将永远不会收到计时器事件。
标签: c++ multithreading qt qthread qtimer