PDA

View Full Version : How to run a QProcess in QThread without destroying the QThread



INeedADollar
3rd August 2019, 19:28
Hello! I don't get how to run a QProcess with QThread. Please help me, I tried also with both worker class and run() method but it doesn't work. I get: "QThread: desztroyed while thread is still running".
Here is my code:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
class mainWindow : public QWidget
{
Q_OBJECT
//here are defined some variables
public:
mainWindow(QWidget *parent = 0);
~mainWindow();
void createUI();
void process();
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include <QWidget>
#include <QPushButton>
#include <QProcess>
#include <QByteArray>
#include <QTextCodec>
#include <QString>
#include <QDebug>
#include "mainwindow.h"

mainWindow::mainWindow(QWidget *parent) : QWidget(parent)
{
createUI();
}


mainWindow::~mainWindow()
{

}
void mainWindow::createUI(){
//here I create the look of the window
QPushButton buttonsearch = new QPushButton("Start process", this);
buttonsearch->setToolTip("Start process");
buttonsearch->setGeometry(200, 290, 100, 30);
connect(buttonsearch, &QPushButton::clicked, [this]() {process(); });
}

void mainWindow::process(){
process->setProcessChannelMode(QProcess::MergedChannels);
process->start("\"D:\\YTDownloader\\youtube-dl.exe\" -e --no-playlist https://www.youtube.com/watch?v=6V-wwfuxZxw");
process->waitForReadyRead();
QByteArray a = process->readAllStandardOutput();
QTextCodec* utfCodec = QTextCodec::codecForName("UTF-8");
QString processStdout = utfCodec->toUnicode(a);
qDebug() << processStdout;
}

main.cpp

#include <QApplication>
#include "mainwindow.h"

int main(int argl,char *argv[])
{
QApplication app(argl,argv);

mainWindow *window = new mainWindow();
window->setWindowTitle("Test");
window->setFixedSize(700, 335);
window->show();

return app.exec();
}

I try to run process() function into a thread when buttonsearch is clicked. Thank you for your help!

wysota
3rd August 2019, 22:42
Why do you want to run QProcess with QThread? The former starts a new process, you don't need a thread for that.

ChrisW67
4th August 2019, 03:28
Why do you want to run QProcess with QThread?
The example code does not use QThread and I think the OP is confusing a thread (managed by QThread) with another process (managed by QProcess)

There seems to be an expectation that waitForReadyRead() does not return until all the process output is available: the call does not work like that, it returns when any of the process output is available. The code needs to either be reworked for a blocking mode of operation or to handle the output as it arrives between the start() call and the termination of the sub-process with slots connected to readyRead() etc. I suspect the latter option is better for a long-running download (like the example) while keeping a responsive UI.

Perhaps INeedADollar can tell us more about the problem.

INeedADollar
4th August 2019, 11:19
Thanks for your response! I need the process in a thread because the window become unresponsive when I start the process.

Added after 6 minutes:

Thanks for your response! I didn't add the thread part because it's something bad in it and I thought someone can show me how to do it right but if you want I send you that part. I need to run the process in a thread because window become unresponsive when I start the process. In my example I try to get the title of videos from YouTube and I will also need a thread to download them, but I will do the download part later.

INeedADollar
4th August 2019, 20:33
I solved it! Thank you for your response. Below is the code if someone is interested:
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
class mainWindow : public QWidget
{
Q_OBJECT
//here are defined some variables
public:
mainWindow(QWidget *parent = 0);
~mainWindow();
void createUI();
void process();
QProcess *process = new QProcess(this);

private slots:
void ReadOutput(int, QProcess::ExitStatus);

};
#endif // MAINWINDOW_H

mainwindow.cpp

#include <QWidget>
#include <QPushButton>
#include <QProcess>
#include <QByteArray>
#include <QTextCodec>
#include <QString>
#include <QDebug>
#include "mainwindow.h"

mainWindow::mainWindow(QWidget *parent) : QWidget(parent)
{
createUI();
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(ReadOutput(int, QProcess::ExitStatus)));
}


mainWindow::~mainWindow()
{

}
void mainWindow::createUI(){
//here I create the look of the window
QPushButton buttonsearch = new QPushButton("Start process", this);
buttonsearch->setToolTip("Start process");
buttonsearch->setGeometry(200, 290, 100, 30);
connect(buttonsearch, &QPushButton::clicked, [this]() {process(); });
}

void mainWindow::process(){
process->setProcessChannelMode(QProcess::MergedChannels);
process->start("\"D:\\YTDownloader\\youtube-dl.exe\" -e --no-playlist https://www.youtube.com/watch?v=6V-wwfuxZxw");

void readOutput(int exitCode, QProcess::ExitStatus exitStatus){
qDebug() << exitCode;
qDebug() << exitStatus;
QByteArray a = process->readAllStandardOutput();
QTextCodec* utfCodec = QTextCodec::codecForName("UTF-8");
processStdout = utfCodec->toUnicode(a);
qDebug() << processStdout;
}

main.cpp

#include <QApplication>
#include "mainwindow.h"

int main(int argl,char *argv[])
{
QApplication app(argl,argv);

mainWindow *window = new mainWindow();
window->setWindowTitle("Test");
window->setFixedSize(700, 335);
window->show();

return app.exec();
}

wysota
4th August 2019, 21:14
You don't have a thread here, you know...

INeedADollar
4th August 2019, 22:14
Yes I know. I don't need the thread I was wrong.

anda_skoa
5th August 2019, 16:07
In your original code your UI became unresponsive because you blocked the main thread in waitForReadyRead()

In Qt most I/O is asynchronous for the very purpose of not blocking the main thread :)

Also, you don't need a lambda here


connect(buttonsearch, &QPushButton::clicked, [this]() {process(); });

you can directly connect to the process() function


connect(buttonsearch, &QPushButton::clicked, this, &mainWindow::process);


Cheers,
_