【问题标题】:How to run functions in different QThreads如何在不同的 QThreads 中运行函数
【发布时间】:2021-03-15 13:43:15
【问题描述】:

如何在不同的QThreads 中运行循环函数?我需要在不同的线程中运行,因为如果我不这样做,循环就会中断。

如何使on_pushTurnOn_clicked在其他线程中执行,pushTurnOn的循环必须能够被on_pushTurnOff_clicked取消,即使在不同的线程上。

MainWindow.h 代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QThread> //I don't know how to use it
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:

        void on_pushTurnOn_clicked();

        void on_pushTurnOff_clicked();

private:

QTimer *timerLoop;

};

#endif // MAINWINDOW_H

MainWindowcpp 代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushTurnOn_clicked()
{
    timerLoop = new QTimer(this);
    timerLoop->setInterval(3000);
    timerLoop->setSingleShot(true);
    connect(timerLoop, SIGNAL(timeout()), 
    SLOT(on_pushTurnOn_clicked()));

    qDebug()<<"the loop was started";
    timerLoop->start(); //start the loop
}

void MainWindow::on_pushTurnOff_clicked()
{
    qDebug()<<"the loop was stoped";
    timerLoop->stop(); //stop the loop
}

【问题讨论】:

  • 这个问题没有完全的意义,但你可以使用 Qthread::run 来达到目的。这就是我从这个问题所了解的全部
  • 请注意,每次输入on_pushTurnOn_clicked() 时都会创建一个新的QTimer。这可能不是您想要的内存泄漏?
  • 一种优雅的方法是在构造函数中分配 QTimer 并连接到完成工作的插槽。在on_pushTurnOn_clicked() 内部,您启动计时器一次(不是单次),在on_pushTurnOff_clicked() 内部,您像现在一样停止计时器。这样您就不需要运行第二个线程。
  • @Aditya 我需要创建第二个线程,这是程序本身的 2%...真正的目的是在主线程上连接一个 PLC,并对另一个进行循环检查可编程逻辑控制器。 (2 个线程用于 2 个不同的 IP)。
  • @JoãoPedro 那么我相信你最好的选择是有第二个类,当你点击按钮时分配它并移动到 QThread。您可以在该线程中设置计时器和工作负载。

标签: c++ multithreading qt loops qthread


【解决方案1】:

我将从旁注开始。您在on_pushTurnOn_clicked() 中为timerLoop 分配的内存将由于没有释放而导致内存泄漏,即使它是单次计时器。您正在创建一个新的QTimer,而不会破坏之前分配的QTimer。更好的方法是在构造函数中只分配一次内存,然后在on_pushTurnOn_clicked() 中启动计时器。

回到你的问题,你必须把你的班级分成两部分,一个是你的mainWindow,它有on_pushTurnOn_clicked()on_pushTurnOff_clicked()的插槽,其他可能的UI元素和非密集任务。

第二个类是一个工人,它包含QTimer 以及实际的工作负载。所以你基本上会有这样的东西:

MainWindow.cpp:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    //constructor
    ui->setupUi(this);
    this->worker = new Worker(); //object of WorkerClass type
    QThread *thread = new QThread();
    worker->moveToThread(thread);
    connect(this, SIGNAL(startOrStopTimerSignal(bool), worker, SLOT(startStopTimer(bool));
}
void MainWindow::on_pushTurnOn_clicked()
{
    if(Busy==1){
        qDebug()<<"Is busy!";
    }
    if(Busy==0){
    FuncaoLoop(RandomParameter1, RandomParameter2);
    }
//start the timer through a signal (timers need to be started in their own threads)
    emit startOrStopTimerSignal(true);
}

void MainWindow::on_pushTurnOff_clicked()
{
    emit startOrStopTimerSignal(false); //stop the timer
}

WorkerClass.h/.cpp:

WorkerClass::WorkerClass(QObject *parent) : QObject(parent)
{
    timerLoop= new QTimer(this);
    connect(timerLoop, SIGNAL(timeout()), this, SLOT(workLoad())); //timer connect to your actual task
}
void WorkerClass::startStopTimer(bool start)
{
    if (start)
        timerLoop->start();
    else
        timerLoop->stop();
}
WorkerClass::workLoad()
{
    //whatever task for your PLC
}

希望对你有所帮助。

【讨论】:

  • 谢谢,这很有帮助!
猜你喜欢
  • 2015-04-25
  • 1970-01-01
  • 2021-06-27
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
相关资源
最近更新 更多