PDA

View Full Version : Thread+send event



Fastman
25th July 2007, 09:14
How to me from a separate thread add a line in listWidget??

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread a93130. Receiver 'HSMClass' (of type 'HSM')

gri
25th July 2007, 10:50
You could implement a slot for addItem() and call QMetaObject::invokeMethod() to call it from a thread.

marcel
25th July 2007, 10:56
Emit a signal from the thread which can contain as parameters data for the item.
Connect this signal to a slot in the GUI thread which will create the item and update the widget.

This is how it must be done.

Another solution is to post a custom event, but is basically the same thing as emitting a signal, only more code to write.

The slot in the GUI will get called asynchronously.

Regards

jpn
25th July 2007, 13:39
QCoreApplication::sendEvent() is not thread-safe but QCoreApplication::postEvent() is. Be sure to read notes in docs.

Fastman
25th July 2007, 14:06
.....
....
thx :o

marcel
25th July 2007, 14:09
.....
....
thx :o

What does that mean?
Aren't you satisfied with the explanations?
Then ask some more?
But first, really, you should search the forum. There have been numerously other similar posts.

Regards

Fastman
25th July 2007, 14:58
No, many thanks, you have very much helped! I have just started to understand with QT, therefore at me it is a lot of questions:)

Fastman
26th July 2007, 16:35
... can help me

my code:


class HSM : public QDialog
{
Q_OBJECT
public:
CProjectManager *m_pPrj;
HSM(QWidget *parent = 0, Qt::WFlags flags = 0);
~HSM();
private:
Ui::HSMClass ui;
Server server;
private slots:
void on_pushButton_clicked();
void SetLine(QString cMsg);
};


HSM::HSM(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{

ui.setupUi(this);

QObject::connect(this, SIGNAL(SendMSG(QString)),
this, SLOT(SetLine(QString cMsg)));// ???????
}

HSM::~HSM()
{
//m_pPrj->FreeInst();
}

void HSM::on_pushButton_clicked()
{
//some code
}

void HSM::SetLine(QString cMsg)
{
ui.listWidget->addItem(cMsg);
}



class FortuneThread : public QThread
{
Q_OBJECT
public:
FortuneThread(int socketDescriptor,QObject *parent);
~FortuneThread();
void run();
signals:
void error(QTcpSocket::SocketError socketError);
private:
int socketDescriptor;
};


FortuneThread::FortuneThread(int socketDescriptor,QObject *parent)
: QThread(parent), socketDescriptor(socketDescriptor)
{

}

FortuneThread::~FortuneThread()
{

}
void FortuneThread::run()
{
Connection connection;
if(!connection.setSocketDescriptor(socketDescripto r))
{
emit error(connection.error());
return;
}
connect(&connection, SIGNAL(disconnected()), this, SLOT(quit()));
exec();
}


class Connection : public QTcpSocket
{
Q_OBJECT
public:
Connection(QObject *parent = 0);
private slots:
void processReadyRead();
signals:
void SendMSG(QString cMsg);

};



Connection::Connection(QObject *parent)
: QTcpSocket(parent)
{
QObject::connect(this, SIGNAL(readyRead()), this, SLOT(processReadyRead()));
}

void Connection::processReadyRead()
{

//some code
//
//
emit SendMSG("new_line");
}


class Server : public QTcpServer
{
Q_OBJECT
public:
Server(QObject *parent = 0);
signals:
void newConnection(Connection *connection);
protected:
void incomingConnection(int socketDescriptor);
};


Server::Server(QObject *parent):QTcpServer(parent)
{
if (!listen(QHostAddress::Any,1718)) {
return;
}
}

void Server::incomingConnection(int socketDescriptor)
{

FortuneThread *thread = new FortuneThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();

}

But at connection of the client record all the same does not appear Where I was mistaken?

marcel
26th July 2007, 16:53
In the constructor of HSM.
There is no signal HSM::SendMSG(). The signal is in Connection. If you look at the debug output you will see a warning.

You could chain the signals. Connect SendMsg to a a signal in the FortuneThread. This signal should be connected in the GUI, to the slot SetLine.

This is because the GUI thread does not have access to Connection.

Where do you instantiate and start the thread?

Regards

Fastman
26th July 2007, 18:05
Where do you instantiate and start the thread?



void Server::incomingConnection(int socketDescriptor)
{
FortuneThread *thread = new FortuneThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}

marcel
26th July 2007, 18:23
Yes, but this line:


QObject::connect(this, SIGNAL(SendMSG(QString)),
this, SLOT(SetLine(QString cMsg)));// ???????
is incorrect.

In incommingConnection, add:


connect(thread, SIGNAL(SendMSG(QString)), this, SLOT(SetLine(QString)));
Add a signal in the FortuneThread class:


void SendMSG(QString);
and in FortuneThread::run(), add:


connect(&connection, SIGNAL(SendMSG(QString)), this, SIGNAL(SendMSG(QString)));
Regards

Fastman
26th July 2007, 19:11
Thanks for your answers, I shall try tomorrow. I shall necessarily write that has turned out:)

marcel
26th July 2007, 21:01
OK. If you do things correctly, it will work.

Regards

Fastman
27th July 2007, 09:09
OK. If you do things correctly, it will work.

Regards


OOOO !!!! Realy Work !!!!!!
Marcel = Guru :)

marcel
27th July 2007, 09:14
OOOO !!!! Realy Work !!!!!!
Marcel = Guru :)

Not really :).
I have about 4000 posts to go until I become a Guru.

Regards

Fastman
1st August 2007, 12:49
I still have a question. The problem in that that after will fulfil Connection:: processReadyRead () process does not come to the end, and all processes remain in memory! How to make that after the termination of processing of connection of the client process it was killed???

marcel
1st August 2007, 12:53
How do you know when a connection should be closed?

Fastman
1st August 2007, 13:12
At me it is as follows written:


void Connection::processReadyRead()
{
QVector<QString> v_File;
char *szData;
QDomDocument doc;
QString cHead = "";
QString cCmd = "";
QString cLogin = "";
QString cPass = "";
QString cGroup = "";
QString cId_proc = "";
QString cFile = "";
QString cObj = "";
QString cPriotity = "";



if( this->isReadable())
{
qint64 qnSize = this->bytesAvailable();
if( qnSize > 0)
{
szData = new char [qnSize];
qint64 qnReadSize = this->read( szData, qnSize);
szData[qnReadSize]=0;
}
}


ParseXML *xml;
xml = new ParseXML(szData);
//xml.Get_Param("head", "");
//cHead = xml.get_param;

xml->Get_Param("login", "");
cLogin = xml->get_param;

xml->Get_Param("pass", "");
cPass = xml->get_param;

xml->Get_Param("cmd", "");
cCmd = xml->get_param;

xml->Get_Param("group", "");
cGroup = xml->get_param;

xml->Get_Param("id_proc", "");
cId_proc = xml->get_param;

xml->Get_Param("priority", "");
cPriotity = xml->get_param;

xml->Get_Param("obj", "name");
cObj = xml->value;

xml->Get_Param("file","");
v_File = xml->vFile;

db_work database;

switch(cCmd.toInt())
{
case 1: //ADD TASK
{
for (int i = 0; i < v_File.size(); ++i)
{
database.AddTask(cCmd, cLogin, cPass, cGroup,
cId_proc, cPriotity, v_File.at(i), cObj);
}

}
break;

case 2: //DELETE TASK
{

}
break;

case 3: //DELETE OBJECT
{

}
break;

case 4: //DELETE FILE
{

}
break;

case 5: //GET INFO
{

}
break;

}

emit SendMSG(szData);

delete(xml);
database.CloseDB();
//QApplication::beep();

this->disconnectFromHost();
if(this->state() == QAbstractSocket::ConnectedState)
this->waitForDisconnected();
}


After that process needs to be finished.

marcel
1st August 2007, 13:26
It means that you don't get the disconnected() signal. If you would, then the quit slot for the thread will get called, causing exec() to exit.

The default delay for waitForDisconnected is 30 seconds.
Try giving it a smaller delay, like 5 seconds ( pass 5000 to waitForDisconnected ).

If you still don't get the disconnected signal, then it means that there is still data pending to be read. But giving it an explicit timeout, it should force a disconnected() signal.

Regards

Fastman
1st August 2007, 13:59
hmmm...

For made comments on a line


.....
.....
.....
this->disconnectFromHost();
// if(this->state() == QAbstractSocket::ConnectedState) - !!!
this->waitForDisconnected(5000);
}


and here that has received in messages

QAbstractSocket::waitForDisconnected() is not allowed in UnconnectedState

marcel
1st August 2007, 14:09
I think the disconnected signal gets messed up.
Move the connect statement from run right after you create the connection.
Just before you call setSocketDescriptor.

Regards.