Qt线程有两种方法:1是继承qthread; 2就是MovetoThread方法;
目的:
第二种方法有其独特的用法,就是可以做成任务槽的方式,做完任务就返回,然后exec进入事件循环,可以避免单一任务频繁创建线程的开销,又可以达到在另一个线程中进行任务的执行;
问题:
在线程中,我想使用个定时器,然后通过点击主线程的按钮来通知此线程的定时器开启和停止;发现会出现”无法关闭在另一个线程的定时器”的提示
解决办法:
无法关闭在另一个线程的定时器,是因为定时器要在新的线程中new,不要在构造函数中new出来,这样定时器才属于另一个线程,而不是创造该线程的主线程中;
以下是项目代码:
Worker.h
#pragma once
#include <QObject>
class QTimer;
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
~Worker();
public slots:
void WorkerTaskStartSlot(void);
void TaskFinished(void);
private slots:
void TimerOutToDoSomethingSlot(void);
signals:
void WorkertResultSig(void);
private:
QTimer *m_pTimer = nullptr;
};
Worker.cpp
#include "Worker.h"
#include <QDebug>
#include <QThread>
#include <QTimer>
Worker::Worker(QObject *parent) : QObject(parent)
{
qDebug()<<__FUNCTION__<<"threadid"<< QThread::currentThreadId();
}
Worker::~Worker()
{
TaskFinished();
qDebug()<<__FUNCTION__<<"threadid"<< QThread::currentThreadId();
}
void Worker::WorkerTaskStartSlot(void)
{
qDebug()<<__FUNCTION__<<"threadid"<< QThread::currentThreadId();
emit WorkertResultSig();
m_pTimer = new QTimer(this);
connect(m_pTimer,&QTimer::timeout,this,&Worker::TimerOutToDoSomethingSlot);
m_pTimer->start(1000);
}
void Worker::TaskFinished(void)
{
qDebug()<<__FUNCTION__<<"threadid"<< QThread::currentThreadId();
if(m_pTimer)
{
if(m_pTimer->isActive())
{
m_pTimer->stop();
qDebug()<<__FUNCTION__<<"stop timer"<< QThread::currentThreadId();
}
delete m_pTimer;
m_pTimer = nullptr;
}
}
void Worker::TimerOutToDoSomethingSlot(void)
{
qDebug()<<__FUNCTION__<<"threadid"<< QThread::currentThreadId();
}
MainWindow.h
#pragma once
#include <QMainWindow>
class QPushButton;
class QWidget;
class Worker;
class QThread;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
void InitCtrl(void);
private slots:
void StartTaskBtnSlot(const bool &checked);
void WorkertResultSlot(void);
private:
QPushButton *m_pStartTaskBtn = nullptr;
QWidget *m_pCenterWidget = nullptr;
Worker *m_pWorker = nullptr;
QThread *m_pWorkerThread = nullptr;
};
MainWindow.cpp
#include "MainWindow.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QWidget>
#include <QDebug>
#include <QThread>
#include "Worker.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
InitCtrl();
qDebug()<<__FUNCTION__<<"mainwindow thread id"<< QThread::currentThreadId();
}
MainWindow::~MainWindow()
{
if(m_pStartTaskBtn->isChecked())
{
m_pStartTaskBtn->click();
}
}
void MainWindow::InitCtrl(void)
{
m_pCenterWidget = new QWidget(this);
m_pStartTaskBtn = new QPushButton(QStringLiteral("Start"),this);
QVBoxLayout *pvertlayout = new QVBoxLayout();
pvertlayout->addWidget(m_pStartTaskBtn);
m_pCenterWidget->setLayout(pvertlayout);
setCentralWidget(m_pCenterWidget);
m_pStartTaskBtn->setCheckable(true);
connect(m_pStartTaskBtn,&QPushButton::clicked,this,&MainWindow::StartTaskBtnSlot);
}
void MainWindow::StartTaskBtnSlot(const bool &checked)
{
if(checked)
{
m_pStartTaskBtn->setText(QStringLiteral("Close"));
m_pWorkerThread = new QThread();
m_pWorker = new Worker();
// move the task object to the thread BEFORE connecting any signal/slots
m_pWorker->moveToThread(m_pWorkerThread);
connect(m_pWorkerThread, SIGNAL(started()), m_pWorker, SLOT(WorkerTaskStartSlot()));
connect(m_pWorker, SIGNAL(WorkertResultSig()), this, SLOT(WorkertResultSlot()));
// automatically delete thread and task object when work is done:
connect(m_pWorkerThread, SIGNAL(finished()), m_pWorker, SLOT(deleteLater()));
connect(m_pWorkerThread, SIGNAL(finished()), m_pWorkerThread, SLOT(deleteLater()));
m_pWorkerThread->start();
}
else
{
m_pStartTaskBtn->setText(QStringLiteral("Start"));
m_pWorkerThread->quit();
m_pWorkerThread->wait();
}
}
void MainWindow::WorkertResultSlot(void)
{
qDebug()<<__FUNCTION__<<"threadid"<<QThread::currentThreadId();
}
结果:
MainWindow::MainWindow mainwindow thread id 0x2bf0
Worker::Worker threadid 0x2bf0
Worker::WorkerTaskStartSlot threadid 0x4af0
MainWindow::WorkertResultSlot threadid 0x2bf0
Worker::TimerOutToDoSomethingSlot threadid 0x4af0
Worker::TimerOutToDoSomethingSlot threadid 0x4af0
Worker::TimerOutToDoSomethingSlot threadid 0x4af0
Worker::TimerOutToDoSomethingSlot threadid 0x4af0
Worker::TaskFinished threadid 0x4af0
Worker::TaskFinished stop timer 0x4af0
Worker::~Worker threadid 0x4af0
项目源码下载地址:
版权声明:本文为u010505080原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。