QThread created in other QThread not calling destructor - qt

I have a code:
#include <QApplication>
#include <QThread>
#include <QDebug>
class ChildThread : public QThread {
Q_OBJECT
public:
ChildThread() {
connect(this, &QThread::finished, this, &ChildThread::deleteLater);
}
~ChildThread() {
qDebug() << "~TR()";
}
protected:
void run() {
qDebug() << "RUN";
}
};
class ParentThread : public QThread {
Q_OBJECT
public:
protected:
void run() {
for (int i = 0; i < 10; i++) {
ChildThread *t = new ChildThread();
t->start();
msleep(1000);
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ParentThread *t = new ParentThread();
t->start();
for (int i = 0; i < 10; i++) {
ChildThread *t = new ChildThread();
t->start();
QThread::msleep(1000);
}
return a.exec();
}
And I havnt understand, why all of the ChildThread that created in the ParentThread after reaching end of run() function not ending and desctructor of the ChildThread not called, but if I create ChildThread outside of ParentThread, deststructor of ChildThread was called?
Thank You!

The thread will not be destroyed when the run() function due to the
fact that the deleteLater() function is called when the parent (main) loop
get back the control.
Creating the ChildThread from main(), the QThread::msleep() call
give back the control to the main loop, so the destructor can be
called.

Related

Qt Signal Slot connection issue

Trying to create 2 objects (clients) living in different threads and communicating with 1 object(server) living on the main thread.
However I'm not seeing any activity on the server object.
The main goal of this code is to see how the signal slot will behave when 2 signals coming from 2 different threads are communicating with a single object on the main thread.
objects.cpp:
#include "objects.h"
Objects::Objects(QObject* parent): QObject (parent)
{
}
void Objects::printData(const QString& data)
{
qDebug() << data;
}
void Objects::process(const QString& data)
{
emit sendData(data+":processed");
}
Q_NORETURN void Objects::run()
{
while (true) {
//qDebug() << "hit" << m_rate;
emit sendData("test"+QString::number(m_rate));
QThread::sleep(m_rate);
}
}
objects.h:
#ifndef OBJECTS_H
#define OBJECTS_H
#include <QObject>
#include <QDebug>
#include <QThread>
class Objects: public QObject
{
Q_OBJECT
public:
explicit Objects(QObject* parent = Q_NULLPTR);
signals:
void sendData(const QString&);
public slots:
void printData(const QString&);
void process(const QString&);
void run();
public:
ulong m_rate;
};
#endif // OBJECTS_H
main.cpp:
#include <QCoreApplication>
#include "objects.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Objects ser;
Objects cl1;
Objects cl2;
cl1.m_rate = 1;
cl2.m_rate = 2;
QThread cl1_t;
QThread cl2_t;
QObject::connect(&cl1_t, &QThread::started, &cl1, &Objects::run);
QObject::connect(&cl2_t, &QThread::started, &cl2, &Objects::run);
QObject::connect(&cl1, &Objects::sendData, &ser, &Objects::process);
QObject::connect(&cl2, &Objects::sendData, &ser, &Objects::process);
QObject::connect(&ser, &Objects::sendData, &cl1, &Objects::printData);
QObject::connect(&ser, &Objects::sendData, &cl2, &Objects::printData);
cl1.moveToThread(&cl1_t);
cl2.moveToThread(&cl2_t);
cl1_t.start();
cl2_t.start();
return a.exec();
}
Looks like your void run() function-member blocks Qt internal event queue. Just add QCoreApplication::processEvents(); in to your void run() and it will solve your problem.
void Objects::run()
{
while (true) {
qDebug() << "hit" << m_rate;
emit sendData("test" + QString::number(m_rate));
QThread::sleep(m_rate);
QCoreApplication::processEvents();
}
}
UPD:
I will suggest you to read THIS wiki article for more detailed explanation on your problem.

declaring qtcpsocket class object as global

I am working on qt to develop a socket programming.i am posting the code here.
"mainwindow.h"
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
namespace Ui {
class MainWindow;
}
static void handler(int sig, siginfo_t *si, void *uc);
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QTcpSocket *socket;
void timer();
void config();
private slots:
void newconnection();
private:
Ui::MainWindow *ui;
QTcpServer *server;
};
#endif // MAINWINDOW_H
"mainwindow.cpp"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
static char i;
ui->setupUi(this);
sock=socket;
// if(!i)
// {
// connect(ui->start_button,SIGNAL(clicked()),this,SLOT(config()));
// }
// i=1;
qDebug()<<i;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow ::newconnection()
{
static int i;
socket=server->nextPendingConnection();
//connect(socket,SIGNAL(readyRead()),this,SLOT(timer_data_recieve()));
qDebug()<<"new connection";
qDebug()<<"server is reading..."<<socket->bytesAvailable();
qDebug()<<socket->readAll();
//time->start(1000); //QT timer started
if(!i)
timer();
i=1;
}
void MainWindow::timer()
{
timer_t t_id;
struct sigaction sa;
struct sigaction arg;
struct sigevent s_evnt;
struct itimerspec timer;
/* Establish handler for notification signal */
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
s_evnt.sigev_notify = SIGEV_SIGNAL;
s_evnt.sigev_signo = SIGRTMAX;
s_evnt.sigev_value.sival_ptr = &t_id;
if (sigaction(SIGRTMAX, &sa,NULL) == -1)
{
perror("sigaction");
}
//==============timer vlaues==============
timer.it_value.tv_sec=0;
timer.it_value.tv_nsec=20000000;
timer.it_interval.tv_sec=0;
timer.it_interval.tv_nsec=20000000;
if(timer_create(CLOCK_REALTIME,&s_evnt,&t_id)==-1);
perror("timer create");
if(timer_settime(t_id,0,&timer,NULL)==-1)
perror("timer_set_time");
}
void MainWindow::config()
{
//time=new QTimer(this);
server=new QTcpServer(this);
socket=new QTcpSocket(this);
connect(server,SIGNAL(newConnection()),this,SLOT(newconnection()));
// connect(time,SIGNAL(timeout()),this,SLOT(timer_data_sending()));
if(server->listen(QHostAddress::LocalHost,600))
{
qDebug()<<"server started";
}
else
qDebug()<<"server not started";
qDebug()<<MainWindow::server->errorString();
}
static void handler(int sig, siginfo_t *si, void *uc)
{
// MainWindow w;
qDebug("in handler");
// MainWindow *s = static_cast<MainWindow*>(&w);
static char first_call=1;
static unsigned sec;
static long nsec;
struct timespec start;
struct timespec curr;
if (first_call) {
first_call = 0;
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
perror("clock_gettime");
}
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
perror("clock_gettime");
sec = (curr.tv_sec - start.tv_sec);
nsec = (curr.tv_nsec - start.tv_nsec);
if (nsec < 0)
{
sec--;
nsec += 1000000000;
}
start = curr;
}
"main.cpp"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
w.config();
return a.exec();
}
here evrything is working fine about handler.
but if want to access the handler data to socket to send to client,one way is to declare socket is global.but how to decalre globally to access in mainwindow member functions and as well as in handler?
please suggest me.it is very important to me .please don't avoid it.
NOTE:qtimer is not neded here
You can use Singletone Design Pattern architecture for your TCP Socket class. You need to create class that extends QTcpSocket. So you will create only one object and access the same globally using get_instance() method, as it is public static in this design pattern. You can go through Singleton design pattern
The documentation contains a good example about how to implement a Singleton and export it from C++ to QML.

Qt slot connected successful but wasn't fired

I try to call slot of my class via newConnection() signal of QTcpServer class. connect() function returns true, but the slot weren't executed.
Here's what i made:
class server : QObject
{
Q_OBJECT
public:
server();
QTcpServer *srv;
void run();
public slots:
void handleClient();
}
Bind the slot:
void server::run()
{
srv = new QTcpServer();
bool status = connect(srv, SIGNAL(newConnection()), this, SLOT(handleClient()));
// status contains true now
srv->listen(QHostAddress::Any, port);
}
Slot's body:
void server::handleClient()
{
/* This code is not being executed */
qDebug() << "zxc";
QMessageBox msg;
msg.setText("zxc");
msg.exec();
}
Why doesn't it work?
I'm not quite sure what you're doing wrong try adding public in the inheritance line (: public QObject).
The following code works for me:
server.hpp
#ifndef _SERVER_HPP_
#define _SERVER_HPP_
#include <QtNetwork>
class Server : public QObject
{
Q_OBJECT
public:
Server();
private slots:
void handleClient();
private:
QTcpServer* mServer;
};
#endif
server.cpp
#include "server.hpp"
Server::Server() : mServer(new QTcpServer())
{
connect(mServer, SIGNAL(newConnection()), this, SLOT(handleClient()));
mServer->listen(QHostAddress::Any, 10000);
}
void Server::handleClient()
{
while (mServer->hasPendingConnections())
{
QTcpSocket* skt = mServer->nextPendingConnection();
skt->write("READY\n");
skt->waitForReadyRead(5000);
qDebug() << skt->readAll();
skt->write("OK\n");
skt->waitForBytesWritten();
skt->close();
skt->deleteLater();
}
}
main.cpp
#include "server.hpp"
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
Server srv;
return app.exec();
}

Does QTimer resuse unique id?

I looked in the documentation and I didn't find something about reusing unique Id.
The documentation says about the startTimer function:
The function returns a unique integer timer ID
But how long will it be unique? Does it reuse the ids at some point?
But how long will it be unique?
The timer ID should remain unique until it is released via QAbstractEventDispatcherPrivate::releaseTimerId();
In other words, calling killTimer().
Does it reuse the ids at some point?
I quickly wrote a simple test to see if the timer ID would get reused:
Something.h:
#include <QCoreApplication>
#include <QtCore>
#include <QtGlobal>
class Something : public QObject
{
Q_OBJECT
public:
Something() : QObject() {}
~Something() {}
};
main.cpp:
#include "Something.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Something thing;
int i = thing.startTimer(1000);
qDebug() << i;
thing.killTimer(i);
i = thing.startTimer(1000);
qDebug() << i;
return a.exec();
}
The result:
1
1
Finally, using QTimer exclusively... you can test with:
class Something : public QObject
{
Q_OBJECT
public:
Something() : QObject(), timer(NULL) {}
~Something() {}
void runme()
{
timer = new QTimer();
// Old school ;)
QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
timer->start(100);
}
public Q_SLOTS:
void timerEvent()
{
qDebug() << timer->timerId();
timer->stop();
delete timer;
timer = new QTimer();
QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
timer->start(1000);
}
public:
QTimer* timer;
};
Then just kick it off and run it:
Something thing;
thing.runme();

Qt creating children threads using QFuture error

I am trying to make a Collaborative Editor(I have to use Linux networking libraries for all the networking stuff), I have the main widget(custom made class that inherits QWidget) with all the components. In the constructor I create all the Widgets on this main Widget and at the end I try to create a new thread using QFuture(I use QFuture instead of QThread cause it allows me easily to call functions with any type of parameters, like QTextEdit, QTextCursor...) but it gives me this error at compilation:
"QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x1b064b0), parent's thread is QThread(0x1985750), current thread is QThread(0x1ae7610)".
How to solve the error?
Here is my code:
mainwindow.h:
...//includes
using namespace QtConcurrent;
...
namespace Ui {
class Widget;
class TextEdit;
}
class TextEdit;
class Widget;
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
...
QFuture<void> thread;
}
class TextEdit : public QTextEdit {
Q_OBJECT
...
}
static void receiveKeyPress(TextEdit *textedit, QTextCursor *secondUserCursor) {
unsigned long long int Number = NULL;
QMessageBox::information(textedit->parentWidget(), "UI Component", "This makes the thread to throw the error");
while(1) if(connected == 1) {
read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
if( Number != NULL)
if( Number == Qt::Key_Home )
secondUserCursor->movePosition(QTextCursor::StartOfLine);
...
else {
QTextCharFormat backgroundFormat = textedit->textCursor().charFormat();
backgroundFormat.setBackground(QColor("lightGreen"));
//If I don't use QMessageBox up there, it breaks here on the next command
secondUserCursor->setCharFormat(backgroundFormat);
secondUserCursor->setPosition(textedit->textCursor().position());
secondUserCursor->insertText(QString::number(Number));
} //else
}//while
}//the function
And mainwindow.cpp:
#include "mainwindow.h"
Widget::Widget(QWidget *parent) {
...
thread = run(receiveKeyPress, this->edit1, this->edit1->secondUserCursor); //run is from QtConcurrent namespace
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
...
window.show();
return a.exec();
}
I've read here on stackoverflow how others use QObject(which I never used and I don't get the idea of it) and QThread(the only combination) but I already tried to use QThread and I wasn't able to pass QTextEdit and QTextCursor to it.
Thanks in advance
Edit:
mainwindow.h
class TextEdit : public QTextEdit {
Q_OBJECT
...
public slots:
void receiveKeyPress(qulonglong);
...
};
mainwindow.cpp
void TextEdit::receiveKeyPress(qulonglong Number) {
if( Number == Qt::Key_Home )
...
}
recv-thread.h - created based on this link http://developer.qt.nokia.com/doc/qt-4.8/thread-basics.html#example-3-clock
#include <QThread>
#include "mainwindow.h" //To get TextEdit in here
class RecvThread : public QThread {
Q_OBJECT
signals:
void transferDataToSlot(qulonglong Data);
protected:
void run();
};
recv-thread.cpp
#include "recv-thread.h"
void RecvThread::run() {
unsigned long long int Number = NULL;
while(1) if(connected == 1) {
read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
if( Number != NULL) {
emit transferDataToSlot(Number);
}
}
}
main.cpp
...
#include "recv-thread.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget window;
RecvThread recvThread;
...
QObject::connect(&recvThread, SIGNAL(transferDataToSlot(qulonglong)), window.edit1, SLOT(receiveKeyPress(qulonglong)), Qt::QueuedConnection); //line 38
recvThread.start();
//Displaying the window
window.show();
a.exec();
recvThread.quit();
recvThread.wait();
return 0;
}
Am I doing it right?

Resources