Dazed
1st July 2010, 21:25
Hello
I am trying to educate myself in how QT Threads can be used in a Console-based application. On each QThread I'm using QNetworkAccessManager to post SOAP messages and process responses to target systems - this to simulate a monitoring requirement I have.
I have this working, but not as I expected. Rather than the send and receive events being handled on specific threads they all seem to be happening on main thread.
Here's my output (apologies haven't used this forum before, so not sure how to make code standout):
Thread [0x1550] started running
Main Thread [0x1578] Starting main Application event loop
Thread [0xb74] started running
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Response [Data back]
Thread [0x1578] Response [Data back]
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Response [Data back]
Thread [0x1578] Response [Data back]
I have an app.exec() in main() [main thread]
and an exec() in each created thread
and am using singnals and slots to start the sending, process network response and QTimer to pause before next send...ad infinitum
My suspicion is that I haven't got my signals and slots correctly setup and all events are being managed by the app.exec() and my actual threads are effectively orphaned. Am I missing something?
I'm doing this on Windows Vista and QT 4.6.2 if that makes any difference.
Here's my code:
main() function
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// start two Threads
for (int i=0; i<2; i++) {
opMyThread[i] = new MyThread();
opMyThread[i]->start();
}
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Main Thread [" << app.thread()->currentThreadId() << "] Starting main Application event loop" << std::endl;
}
return app.exec();
}
The QThread run() function - which I think is the code that
void MyThread::run() {
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] started running" << std::endl;
}
connect(this, SIGNAL(readyToSend()), this, SLOT(sendData()));
// kicks off the send/receive event cycle
emit readyToSend();
exec();
}
send data function - supposed to be called on the thread, but appears to be called from main thread
void MyThread::sendData() {
//had problems with creating QNetworkAccessManager anywhere else (child/parent assertions)
if (opNetManager == 0) {
opNetManager = new QNetworkAccessManager();
connect(opNetManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
}
QByteArray sendData = "<Data>Data Sent</Data>";
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] Send [Data Sent]" << std::endl;
}
QNetworkRequest rqst(QUrl("http://localhost:8080/mytarget"));
rqst.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml");
rqst.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
opNetManager->post(rqst, sendData);
}
and finally the slot function to handle network replys
void MyThread::replyFinished(QNetworkReply* reply) {
QByteArray data = reply->readAll();
if (reply->error() == QNetworkReply::NoError) {
QTextStream out(&data);
QString replyString;
replyString.append(data);
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] ";
std::cout << "Response [" << replyString.toAscii().constData() << "]" << std::endl;
}
} else {
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] ";
std::cout << "Response [" << reply->error() << "]" << std::endl;
std::cout << "Response [" << reply->errorString().toAscii().constData() << "]" << std::endl;
}
}
reply->deleteLater();
// emit the send again with wait
QTimer::singleShot(2000, this, SIGNAL(readyToSend()));
}
Any help or education greatly received.
I am trying to educate myself in how QT Threads can be used in a Console-based application. On each QThread I'm using QNetworkAccessManager to post SOAP messages and process responses to target systems - this to simulate a monitoring requirement I have.
I have this working, but not as I expected. Rather than the send and receive events being handled on specific threads they all seem to be happening on main thread.
Here's my output (apologies haven't used this forum before, so not sure how to make code standout):
Thread [0x1550] started running
Main Thread [0x1578] Starting main Application event loop
Thread [0xb74] started running
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Response [Data back]
Thread [0x1578] Response [Data back]
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Send [Data Sent]
Thread [0x1578] Response [Data back]
Thread [0x1578] Response [Data back]
I have an app.exec() in main() [main thread]
and an exec() in each created thread
and am using singnals and slots to start the sending, process network response and QTimer to pause before next send...ad infinitum
My suspicion is that I haven't got my signals and slots correctly setup and all events are being managed by the app.exec() and my actual threads are effectively orphaned. Am I missing something?
I'm doing this on Windows Vista and QT 4.6.2 if that makes any difference.
Here's my code:
main() function
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// start two Threads
for (int i=0; i<2; i++) {
opMyThread[i] = new MyThread();
opMyThread[i]->start();
}
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Main Thread [" << app.thread()->currentThreadId() << "] Starting main Application event loop" << std::endl;
}
return app.exec();
}
The QThread run() function - which I think is the code that
void MyThread::run() {
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] started running" << std::endl;
}
connect(this, SIGNAL(readyToSend()), this, SLOT(sendData()));
// kicks off the send/receive event cycle
emit readyToSend();
exec();
}
send data function - supposed to be called on the thread, but appears to be called from main thread
void MyThread::sendData() {
//had problems with creating QNetworkAccessManager anywhere else (child/parent assertions)
if (opNetManager == 0) {
opNetManager = new QNetworkAccessManager();
connect(opNetManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
}
QByteArray sendData = "<Data>Data Sent</Data>";
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] Send [Data Sent]" << std::endl;
}
QNetworkRequest rqst(QUrl("http://localhost:8080/mytarget"));
rqst.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml");
rqst.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
opNetManager->post(rqst, sendData);
}
and finally the slot function to handle network replys
void MyThread::replyFinished(QNetworkReply* reply) {
QByteArray data = reply->readAll();
if (reply->error() == QNetworkReply::NoError) {
QTextStream out(&data);
QString replyString;
replyString.append(data);
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] ";
std::cout << "Response [" << replyString.toAscii().constData() << "]" << std::endl;
}
} else {
if (true) { QMutexLocker Lock(&gmOutput);
std::cout << "Thread [" << currentThreadId() << "] ";
std::cout << "Response [" << reply->error() << "]" << std::endl;
std::cout << "Response [" << reply->errorString().toAscii().constData() << "]" << std::endl;
}
}
reply->deleteLater();
// emit the send again with wait
QTimer::singleShot(2000, this, SIGNAL(readyToSend()));
}
Any help or education greatly received.