计时器是否从另一个线程启动?
Is the timer being started from another thread?
QThread 文档提出了两种使代码在单独线程中运行的方法。如果我子类 QThread 并重新实现 run((,那么我得到
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();
};
关于第一个(非moveToThread
(示例...
快速浏览一下Qt源代码QBasicTimer::start
显示以下内容...
void QBasicTimer::start(int msec, QObject *obj)
{
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
// ...
if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) {
qWarning("QBasicTimer::start: Timers cannot be started from another thread");
return;
}
因此,它期望其第二个参数obj
具有与当前线程相等的线程亲和力。
但是,在您的Worker::run
实施中,您...
timer.start(1000, this);
在此上下文中,当前线程是由QThread
实例创建的新线程,但this
是指MainWidget
在主 GUI 线程上创建QWorker
的新线程。 因此警告。
编辑 1:
对于问题...
为什么它适用于 moveToThread((?
考虑MainWidget
ctor 的实现...
MainWidget()
{
worker = new Worker;
worker->moveToThread(&thread);
connect(this, &MainWidget::start, worker, &Worker::run);
thread.start();
emit start();
}
调用Worker::run
时,Worker
实例已移动到新线程。 所以当线...
timer.start(1000, this);
执行时,this
(指Worker
实例(位于当前线程上,并且QBasicTimer::start
中的线程关联性测试将在不发出警告的情况下通过。
抱歉,如果上述内容有点复杂,但重要的是考虑第二个参数对QBasicTimer::start
的线程亲和力:它必须是当前正在运行的线程。
相关文章:
- 使用 std::string () const 函数启动线程或未来
- C++ POCO - 如何在不使用 run() 方法的情况下启动线程池上的线程?
- 使用 std::thread & std::bind 在成员函数中启动线程
- GDB 输出启动线程,但给出输出
- 尝试在我的基类中启动线程时,Visual Studio 由于调试错误而中止我的程序
- 启动线程会导致指针初始化时出现分段错误
- OMP 不启动线程
- 在关闭时升级登录中的启动线程访问违规
- 如何在dllmain中启动线程
- 如何使用媒体基础在给定时间运行/启动线程
- 如何在另一个核心上启动线程而不将处理器亲和力设置为特定核心
- Qt多线程启动线程错误
- 在构造函数中使用"this"启动线程是安全的?
- 停止,然后启动线程
- C++/Win32 我在 Windows 2000+ 上启动线程的最佳方式
- 如何在事件发生时启动线程并严格关闭其句柄
- 从 Poco::HTTPServer 启动线程
- 在成员函数上启动线程时不需要的析构函数调用
- C++线程库,在完成前两个线程后启动线程
- 使用父窗口在对象中启动线程