PDA

View Full Version : Emit signal outside run() in QThread



naturalpsychic
23rd March 2012, 04:44
Hello everyone,

I have three class
Server : QTcpServer
ServerThread : QThread

and main class (GUI)

Have a look at my code.

#ifndef SERVER_H
#define SERVER_H

#include <QTcpServer>
#include <QByteArray>

class ServerThread;
class Dialog;

class Server : public QTcpServer
{
Q_OBJECT
private:
Dialog *parent_;
public:
explicit Server(Dialog *parent);
void incomingConnection(int socketDescriptor
);
void startServer(int);
signals:
void received(QString data);
public slots:
void onreceived(QString data);
};

#endif // SERVER_H

#ifndef SERVERTHREAD_H
#define SERVERTHREAD_H

#include <QThread>
#include <QByteArray>
#include "dialog.h"
class QTcpSocket;

class ServerThread : public QThread
{
Q_OBJECT
private:
int socketDescriptor_;

Dialog *parent_;
public:
explicit ServerThread(int socketDescriptor,Dialog *parent);
QTcpSocket *tcpSocket;
void run(void);
bool emit_signal;
signals:
void received_sgl(QString str);
public slots:
void received(void);
void disconnected(void);

};

#endif // SERVERTHREAD_H

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QString>
#include <QByteArray>
namespace Ui {
class Dialog;
}

class QTcpSocket;
class Server;
class Dialog : public QDialog
{
Q_OBJECT

public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
QTcpSocket *socket;
Server *s;

void update(QString s);

private slots:
void on_pushButton_2_clicked();
void on_pushButton_clicked();
void received();
void rcd_(QByteArray arr);


signals:
private:
Ui::Dialog *ui;
};

#endif // DIALOG_H




and following implementation


SERVER.cpp

#include "server.h"
#include "serverthread.h"
#include <QDebug>
Server::Server(Dialog *parent) :
QTcpServer(parent),parent_(parent)
{
}
void Server::startServer(int port)
{

this->listen(QHostAddress::Any,port);
qDebug()<<"listening!";
}

void Server::incomingConnection(int socketDescriptor)
{
qDebug()<<"Server::incomming connection";
ServerThread *thread=new ServerThread(socketDescriptor,parent_);
connect(thread,SIGNAL(received_sgl(QString)),this, SLOT(onreceived(QString)));
connect(thread,SIGNAL(finished()),thread,SLOT(dele teLater()));
thread->start();

}


void Server::onreceived(QString data)
{
qDebug()<<"updating...::::"<<QString(data);
parent_->update("updating..."+data);


}

ServerThread.cpp
#include "serverthread.h"
#include <QTcpSocket>
#include <QDebug>



ServerThread::ServerThread(int socketDescriptor,Dialog *parent) :
QThread(parent),socketDescriptor_(socketDescriptor ),parent_(parent)
{

}




void ServerThread::run()
{
tcpSocket=new QTcpSocket(parent_);
tcpSocket->setSocketDescriptor(socketDescriptor_);

connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(re ceived()),Qt::DirectConnection);
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT (disconnected()),Qt::DirectConnection);

qDebug()<<"ServerThread::run";

exec();
}


void ServerThread::received()
{

qDebug()<<"ServerThread::received()"<<QString(tcpSocket->readAll());

emit received_sgl(QString(tcpSocket->readAll()));

if (tcpSocket->isWritable())
{
tcpSocket->write(QByteArray("writing..."));

}
}

void ServerThread::disconnected()
{
tcpSocket->deleteLater(); //delete tcpSocket once exit() for thread is executed
exit(); //exit the thread
}

Dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include "server.h"

#include <QTcpSocket>
#include <QDebug>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);

s=new Server(this);
socket=new QTcpSocket(this);

QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(received()));
QObject::connect(s, SIGNAL(received(QByteArray)), this, SLOT(rcd_(QByteArray)));

}

Dialog::~Dialog()
{
delete ui;
}
void Dialog::rcd_(QByteArray arr)
{
ui->lblmsg->setText(QString(arr));
qDebug()<<QString(arr);
}

void Dialog::on_pushButton_2_clicked()
{


s->startServer(ui->lineEdit->text().toInt());
ui->lineEdit->setEnabled(false);

}
void Dialog::received()
{
qDebug()<<"received by client";

update(QString(socket->readAll()));

}

void Dialog::on_pushButton_clicked()
{
qDebug()<<"sending...";
socket->open(QAbstractSocket::ReadWrite);

socket->connectToHost(ui->lineEdit_3->text(),ui->lineEdit_2->text().toInt());
socket->write("write now");

socket->close();
// socket->close();
//delete socket;

}

void Dialog::update(QString s)
{
ui->lblmsg->setText(s);
}



it works fine and emits signal and is caught my slot. But by the time slot catches the signal "data" is already lost

could someone spot out problem?

(if i need to emit signal in run() i have tried to do it using boolean flag but didn't quite work)


Thank you so much for your time

ChrisW67
23rd March 2012, 06:08
I really don't know why people insist on using threads in (presumably) low volume servers. It only serves to complicate.

Anyway. At line 69 of your implementation you read all the available data to dump to debug. When you then try to read all the same data again at line 71 it is hardly surprising that there is no more.

naturalpsychic
23rd March 2012, 08:56
Thanks :)

Yea I normally dont do that, this was just a test example.

Now i have a little problem. If i run in debug mode it runs fine and if i run it in non-debug mode that means just play button in qt creator it crashes with Visual C++ runtime error

Any idea why?

wysota
23rd March 2012, 11:16
Most probably an uninitialized pointer somewhere.

naturalpsychic
26th March 2012, 16:31
Just for anyone curious about answer to this is:

I used signal and slot mechanism in MyThread : QThread

Additionally, the crash was because of DirectConnection in signal (line: 57)