Results 1 to 5 of 5

Thread: Multi-threading in Console QCoreApplication

  1. #1
    Join Date
    Jul 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    Windows
    Thanked 1 Time in 1 Post

    Default Multi-threading in Console QCoreApplication

    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.

  2. #2
    Join Date
    May 2010
    Posts
    30
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    2
    Thanked 1 Time in 1 Post

    Default Re: Multi-threading in Console QCoreApplication

    You probably need: moveToThread(this) in the constructor for 'MyThread' otherwise your 'this' pointer will be referencing an object "owned" by the main thread, and all signals and slots will be tied to there.

  3. #3
    Join Date
    Jul 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    Windows
    Thanked 1 Time in 1 Post

    Default Re: Multi-threading in Console QCoreApplication

    That's it !, many thanks

    Now this outputs...
    Qt Code:
    1. Thread [0x1438] started running
    2. Main Thread [0x430] Starting main Application event loop
    3. Thread [0x11a8] started running
    4. Thread [0x1438] Send [Data Sent]
    5. Thread [0x11a8] Send [Data Sent]
    6. Thread [0x1438] Response [Data back]
    7. Thread [0x11a8] Response [Data back]
    8. Thread [0x1438] Send [Data Sent]
    9. Thread [0x11a8] Send [Data Sent]
    10. Thread [0x11a8] Response [Data back]
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Belgium
    Posts
    1,938
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanked 268 Times in 268 Posts
    Wiki edits
    20

    Default Re: Multi-threading in Console QCoreApplication


  5. The following user says thank you to tbscope for this useful post:

    totem (5th July 2010)

  6. #5
    Join Date
    Jul 2010
    Posts
    6
    Qt products
    Qt4
    Platforms
    Windows
    Thanked 1 Time in 1 Post

    Default Re: Multi-threading in Console QCoreApplication

    That's a very interesting blog and set of comments. Think "wrong" may be a little harsh especially given documentation pointers. Certainly helps explain a little more about what is going on and the importance of QObject::moveToThread().

    So I have re-factored my code to create a separate Worker object and QThread object then move the Worker to the QThread.

    In doing this I have noticed a couple of potential gotchas - which I thought I'd share.

    #1: It 's important to create objects 'owned' by the Worker as children. So to use "new QNetworkAccessManager(this);" as the documentation for Object::moveToThread() states "Changes the thread affinity for this object and its children".

    #2: The timing of when QNetworkAccessManager seems to be important.
    When I create the QNetworkAccessManager in the Worker object constructor (with (this) as above) then I get:
    Qt Code:
    1. Thread [0x1380] Send [Data Sent]
    2. QObject::startTimer: timers cannot be started from another thread
    3. Thread [0x1380] Response [Data back]
    To copy to clipboard, switch view to plain text mode 

    The only way that I can get this to work is to create the QNetworkAccessManager and form the connect for QNetworkAccessManager::finished() is just before first use.

    By this time of course the Worker object has been 'moved' and the Thread is active. So any new objects appear to have correct affinity. BTW - doesn't seem to matter if it's created with (this) or not.

    So I have it working in both modes (over-riding QThread and separate objects). Both of these points relate to both modes. However for #2 my solution feels a little like a work-around - so I may of course have missed something else here.

  7. The following user says thank you to Dazed for this useful post:

    Koas (15th October 2011)

Similar Threads

  1. Slow Multi-Threading
    By AwDogsgo2Heaven in forum Qt Programming
    Replies: 5
    Last Post: 19th July 2009, 22:36
  2. Multi-threading
    By lixo1 in forum Qt Programming
    Replies: 5
    Last Post: 22nd June 2009, 14:22
  3. Console input with QCoreApplication
    By rahman.duran in forum Qt Programming
    Replies: 4
    Last Post: 25th February 2009, 11:37
  4. Multi threading ...
    By kiranraj in forum Qt Programming
    Replies: 2
    Last Post: 18th June 2007, 17:51
  5. Multi-threading
    By shamik in forum Qt Programming
    Replies: 15
    Last Post: 28th November 2006, 11:22

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.