Страницы

Поиск по вопросам

суббота, 14 декабря 2019 г.

QThread Потоки ( как правильно закрыть поток )

#cpp #qt #многопоточность


Привет всем! накидал маленький рабочий пример за 5 минут, но возник вопрос, как правильно
закрыть поток? При старте создаётся новый поток, а старый сохраняется... Возможно,
что то не учёл или сделал не так. Вот исходники:

main.cpp

#include "mainwindow.h"
#include 

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}


mainwindow.cpp

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

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(this->ui->pushButton_start, SIGNAL(clicked()), this, SLOT(startGUI()));
connect(this->ui->pushButton_stop, SIGNAL(clicked()), this, SLOT(stopGUI()));
}

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

void MainWindow::startGUI()
{

// Создание потока
QThread* thread = new QThread;
Worker* worker = new Worker();

// Передаем права владения "рабочим" классом, классу QThread.
worker->moveToThread(thread);

//connect(worker, SIGNAL(sendBool(bool)), this, SLOT(stopGUI(bool)));

// Связываем сигнал об ошибки со слотом обработки ошибок(не показан).
//connect(worker, SIGNAL(error(QString)), this, SLOT(errorHandler(QString)));

// Соединяем сигнал started потока, со слотом process "рабочего" класса, т.е. начинается
выполнение нужной работы.
connect(thread, SIGNAL(started()), worker, SLOT(process()));

// Отображаем в главном потоке Gui, значения из вторичного потока
connect(worker, SIGNAL(sendNumber(int)), this, SLOT(LineEditUi(int)));

// Оповещаем поток, что нужно остановиться
connect(this, SIGNAL(sendNumberBoolStop(bool)), worker, SLOT(reciveBoolStop(bool)),
Qt::DirectConnection);

// По завершению выходим из потока, и удаляем рабочий класс
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));

// Удаляем поток, после выполнения операции
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

thread->start();
}

void MainWindow::LineEditUi(int number)
{
ui->lineEdit->setText(QString::number(number));
}


void MainWindow::stopGUI()
{
Stop = true;
qDebug() << Stop;
sendNumberBoolStop(Stop);
qDebug() << "sendMumberBoolStop = " << Stop;
}


mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include "worker.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

bool Stop;

public slots:
void startGUI();

void stopGUI();
void LineEditUi(int number);

signals:
void sendNumberBoolStop(bool);


private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


worker.cpp

#include "worker.h"
#include 

Worker::Worker(QObject *parent) : QObject(parent)
{
Stop = false;
temp = 0;
}

Worker::~Worker()
{
qDebug() << "destruction Thread";
}


void Worker::process()
{
Stop = false;
if(!Stop == true)
{
    for (temp; temp <= 1000; temp++)
    {
        if(!Stop == true)
        {
        emit(sendNumber(temp));
        //ui->lineEdit->setText(QString::number(temp));
        //QCoreApplication::processEvents();
        qDebug() << temp;
        }
        else
        {
            return;
        }
    }
  }
}


void Worker::reciveBoolStop(bool Numb)
{
Stop = Numb;
qDebug() << "reciveBoolStop = " << Stop;
}


worker.h

#ifndef WORKER_H
#define WORKER_H

#include 

class Worker : public QObject
{
Q_OBJECT
public:
//Worker();
//virtual ~Worker();
explicit Worker(QObject *parent = 0);
~Worker();

bool Stop;
int temp;

signals:
void finished();
//void error(QString err);

void sendNumber(int);

public slots:
void process();

void reciveBoolStop(bool Numb);
};

#endif // WORKER_H


mainwindow.ui



MainWindow



0
0
395
165



MainWindow




 
  
   
  
  
   
    
     Start
    
   
  
  
   
    
     Stop
    
   
  
 






 0
 0
 395
 21





TopToolBarArea


false









    


Ответы

Ответ 1



В приведенном коде не испускается сигнал Worker::finished, следовательно поток не понимает, что ему нужно остановиться. Испустить сигнал нужно на выходе из функции Worker::process. Добавлю, что для задачи единоразово запустить какой-то процесс в отдельном потоке лучше подойдет QtConcurrent::run void MainWindow::startGUI() { Worker* worker = new Worker(); // Отображаем в главном потоке Gui, значения из вторичного потока connect(worker, SIGNAL(sendNumber(int)), this, SLOT(LineEditUi(int))); // Оповещаем поток, что нужно остановиться connect(this, SIGNAL(sendNumberBoolStop(bool)), worker, SLOT(reciveBoolStop(bool)), Qt::DirectConnection); //Запланируем удаление воркера после окончания расчета connect(worker,SIGNAL(finished()), worker,SLOT(deleteLater())); QtConcurrent::run(worker,&Worker::process); }

Комментариев нет:

Отправить комментарий