QThread 中的 QTimer 运行
QTimer running in QThread
我需要一个 class 和一个每 100 毫秒执行一次任务的定时器,这个 class 需要 运行 在一个线程中,所以我想结合 qtimer 和 qthread .
我创建了以下代码:
class Worker : public QObject
{
Q_OBJECT
public:
void setEnabled(bool enable);
public slots:
void initialize();
private:
void doWork();
QTimer *m_timer;
}
void Worker::initialize()
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &Worker::doWork, Qt::DirectConnection);
m_timer->start(100);
}
void Worker::setEnabled(bool enable)
{
if(enable)
m_timer->start(100);
else
m_timer->stop();
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
QThread *thread = new QThread;
Worker *worker = new Worker;
QObject::connect(thread, &QThread::started, worker, &Worker::initialize);
worker->moveToThread(thread);
thread->start();
app.exec();
delete worker;
delete thread;
}
通过以下命令,我可以 enable/disable 时间
worker->setEnabled(false);
worker->setEnabled(true);
我已经测试过,效果很好,但我想知道这是不是正确的方法?
感谢帮助
不,这并不完全正确。
Worker::setEnabled(bool enable)
也应该是一个插槽,因为它直接调用 QTimer::start()
插槽。直接从主线程调用 Worker::setEnabled
会导致未定义的行为。您必须使用 signal-slot 连接从主线程安全地调用 setEnabled
。
您还应该在构造函数中初始化 Worker::m_timer
而不是将其推迟到 initialize()
,这样如果 Worker::setEnabled
是,您就不会 运行 变成悬空指针调用早于预期。 moveToThread
将用它移动 Worker
的所有子级,所以这是非常理智的行为。
我唯一需要提到的是 m_timer 不能在构造函数中初始化。在这里查看来自 qt 的信息:
顺便说一句,这里要注意的一件极其重要的事情是,您永远不应该在 QObject class 的构造函数中分配堆对象(使用 new),因为随后会执行此分配在主线程上而不是在新的 QThread 实例上,这意味着新创建的对象然后由主线程而不是 QThread 实例拥有。这将使您的代码无法工作。相反,在主函数槽中分配此类资源,例如 initialize() 在这种情况下,当调用该对象时,对象将位于新线程实例上,因此它将拥有资源。
我需要一个 class 和一个每 100 毫秒执行一次任务的定时器,这个 class 需要 运行 在一个线程中,所以我想结合 qtimer 和 qthread .
我创建了以下代码:
class Worker : public QObject
{
Q_OBJECT
public:
void setEnabled(bool enable);
public slots:
void initialize();
private:
void doWork();
QTimer *m_timer;
}
void Worker::initialize()
{
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &Worker::doWork, Qt::DirectConnection);
m_timer->start(100);
}
void Worker::setEnabled(bool enable)
{
if(enable)
m_timer->start(100);
else
m_timer->stop();
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
QThread *thread = new QThread;
Worker *worker = new Worker;
QObject::connect(thread, &QThread::started, worker, &Worker::initialize);
worker->moveToThread(thread);
thread->start();
app.exec();
delete worker;
delete thread;
}
通过以下命令,我可以 enable/disable 时间
worker->setEnabled(false); worker->setEnabled(true);
我已经测试过,效果很好,但我想知道这是不是正确的方法?
感谢帮助
不,这并不完全正确。
Worker::setEnabled(bool enable)
也应该是一个插槽,因为它直接调用 QTimer::start()
插槽。直接从主线程调用 Worker::setEnabled
会导致未定义的行为。您必须使用 signal-slot 连接从主线程安全地调用 setEnabled
。
您还应该在构造函数中初始化 Worker::m_timer
而不是将其推迟到 initialize()
,这样如果 Worker::setEnabled
是,您就不会 运行 变成悬空指针调用早于预期。 moveToThread
将用它移动 Worker
的所有子级,所以这是非常理智的行为。
我唯一需要提到的是 m_timer 不能在构造函数中初始化。在这里查看来自 qt 的信息:
顺便说一句,这里要注意的一件极其重要的事情是,您永远不应该在 QObject class 的构造函数中分配堆对象(使用 new),因为随后会执行此分配在主线程上而不是在新的 QThread 实例上,这意味着新创建的对象然后由主线程而不是 QThread 实例拥有。这将使您的代码无法工作。相反,在主函数槽中分配此类资源,例如 initialize() 在这种情况下,当调用该对象时,对象将位于新线程实例上,因此它将拥有资源。