PDA

View Full Version : When I start a thread second time my app is freezing



INeedADollar
19th October 2019, 21:00
Hello! I'm trying to get title of a YouTube video and display it on main window. This operation is blocking my app second time when I press the button from main window so I created a class that represents a QObject and I moved it to another thread. But the same happens, when I start the thread second time my app is not responding.

My code:
title.h


#ifndef TITLE_H
#define TITLE_H

#include <QUrl>
#include <QWidget>
#include <QTextDocument>
#include <QFile>

class Title : public QObject
{
Q_OBJECT
public:
Title(QWidget *parent = nullptr);
~Title();
void searchTile(const QUrl &);
void htmlGet(const QUrl &);

signals:
void titleReady(QString);
void True(QString);

private:
QFile file = QFile("data.json");
QTextDocument h;
bool find(QJsonArray, QString, const QUrl &);
};

#endif // TITLE_H


title.cpp


#include <title.h>
#include <QScopedPointer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRegularExpression>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

Title::Title(QWidget *parent) : QObject(parent){

}

Title::~Title(){

}

void Title::searchTile(const QUrl &url){
if(file.exists() && file.size() != 0){
file.open(QIODevice::ReadOnly | QIODevice::Text); //I have a json file where I save data like title and url of a video
QString val = file.readAll();
file.close();
QJsonDocument d = QJsonDocument::fromJson(val.toUtf8());
QJsonArray list = d.array();
bool checkUrl = this->find(list, "url", url);
if(checkUrl)
emit True("URL is already in download list!"); //this is for showing an error message box
else
this->htmlGet(url);
}
else
this->htmlGet(url);
}

void Title::htmlGet(const QUrl &url) {
QScopedPointer<QNetworkAccessManager> manager(new QNetworkAccessManager);
QNetworkReply *response = manager->get(QNetworkRequest(url));
qDebug() << "titluuuu";
connect(response, &QNetworkReply::finished, [response, this]{
response->deleteLater();
response->manager()->deleteLater();
if (response->error() != QNetworkReply::NoError) return;
auto const contentType =
response->header(QNetworkRequest::ContentTypeHeader).toStrin g();
static QRegularExpression re("charset=([!-~]+)");
auto const match = re.match(contentType);
if (!match.hasMatch() || 0 != match.captured(1).compare("utf-8", Qt::CaseInsensitive)) {
qWarning() << "Content charsets other than utf-8 are not implemented yet:" << contentType;
return;
}
auto const html = QString::fromUtf8(response->readAll());
QRegularExpression rg("eow-title.*>");
auto const m = rg.match(html);
auto s = m.captured(0);
QRegularExpression n("title=.*");
auto a = n.match(s);
h.setHtml(a.captured(0).split("\"")[1]);
emit titleReady(QString(QChar(0x200E)) + h.toPlainText());
}) && manager.take();
}

bool Title::find(QJsonArray arr, QString key, const QUrl &url){
//this function is for searching if a url is already in the json file
for(const auto obj : arr){
if(obj.toObject().value(key) == url.toString().split("&")[0])
return true;
}
return false;

}


mainwindow.h


#include <QWidget>
#include <QThread>
#include <QJsonArray>

class mainWindow : public QWidget
{
Q_OBJECT

signals:
void titleReady(QUrl);

private:
int i = 0;
QThread th;
QJsonArray json;
void displayTitle(QString);
void startWork();
void buttonPushed();
}


mainwindow.cpp


#include "mainwindow.h"
#include "title.h"

mainWindow::mainWindow(QWidget *parent) :
QWidget(parent)
{
title = new Title();
title->moveToThread(&th);
connect(title, &Title::True, this, &mainWindow::errorDialog);
connect(&th, &QThread::finished, title, [this] {qDebug() << "finished"; });
connect(this, &mainWindow::titleReady, title, &Title::searchTile);
connect(&th, &QThread::started, this, &mainWindow::startWork);
connect(title, &Title::titleReady, this, &mainWindow::displayTitle);
}

void mainWindow::buttonPushed(){
th.start()
}

void mainWindow::startWork(){
qDebug() << "Started";
emit titleReady(QUrl(txt->text()));
}

void mainWindow::displayTitle(QString html){
QJsonObject info;

//I have a QComboBox modified with a QTreeView
QModelIndex index_type = type_box->currentView()->rootIndex();
QVariant data_type = type_box->currentView()->model()->data(index_type);
info.insert("type", data_type.toString());

QModelIndex index_ext = type_box->currentView()->currentIndex();
QVariant data_ext = type_box->currentView()->model()->data(index_ext);
info.insert("ext", data_ext.toString());

info.insert("loc", loc_txt->text());
info.insert("title", QJsonValue(html));
info.insert("url", txt->text().split("&")[0]);

json.push_back(info);
QJsonDocument doc(json);
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream text(&file);
text << doc.toJson();
file.close();

//On main window I have a table widget where I want to display some data in it
QTableWidgetItem *item = new QTableWidgetItem(QString(html));
QTableWidgetItem *item1 = new QTableWidgetItem(QString("%1(%2)").arg(data_type.toString(), data_ext.toString()));
QTableWidgetItem *item2 = new QTableWidgetItem(QString("-"));
QTableWidgetItem *item3 = new QTableWidgetItem(QString("-"));
QTableWidgetItem *item4 = new QTableWidgetItem(QString("Waiting..."));

item1->setTextAlignment(Qt::AlignCenter);
item2->setTextAlignment(Qt::AlignCenter);
item3->setTextAlignment(Qt::AlignCenter);
tem4->setTextAlignment(Qt::AlignCenter);

table->setItem(i, 0, item);
table->setItem(i, 1, item1);
table->setItem(i, 2, item2);
table->setItem(i, 3, item3);
table->setItem(i, 4, item4);

i++;
title->thread()->quit();
}


How can I solve this? Only the second time I start the thread, the GUI is freezing and I'm wondering why this happens. I also tried displayTitle() like this:


void mainWindow:: displayTitle (){
qDebug << "test";
title->thread()->quit();
}

but it's the same.

I'm glad if you give me advice for optimization of my code if it's something wrong. Thank you!

ChristianEhrlicher
20th October 2019, 17:13
QTextDocument is a GUI class which should imo not be used inside a thread. I don't see a reason why a thread is needed here at all. Starting a thread a second time is also imo not supported (and also not needed for your task).

INeedADollar
20th October 2019, 18:28
QTextDocument is a GUI class which should imo not be used inside a thread. I don't see a reason why a thread is needed here at all. Starting a thread a second time is also imo not supported (and also not needed for your task).

I agree with you but what can I do to make my gui not freezing because I also tried without another thread and when I clicked the button second time after starting the application always my gui freezed?