Qt的MoveToThread显示无法关闭在另一个线程的定时器---多线程

已于 2022-05-26 16:13:57 修改

阅读量600
 收藏 2

点赞数
分类专栏: QT
版权

qt
c++
开发语言

QT
专栏收录该内容
18 篇文章2 订阅
订阅专栏
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
项目源码下载地址:
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/u010505080/article/details/124863723

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值