Results 1 to 5 of 5

Thread: postEvent and multithreading

  1. #1
    Join Date
    Dec 2008
    Posts
    3
    Thanks
    1

    Default postEvent and multithreading

    Hi,

    Does anyone know what has happened to QApplication:: postEvent and multithreading in Qt 4? If I post an event in another thread than the gui thread, the event is never handled.

    Consider this minimal program:
    Qt Code:
    1. #include <Qt/qapplication.h>
    2. #include <Qt/qthread.h>
    3. #include <iostream>
    4.  
    5. struct Terminator : QObject {
    6. bool event(QEvent* event) {
    7. std::cerr << "Terminator::event" << std::endl;
    8. return true;
    9. }
    10. };
    11.  
    12. int main(int argc, char** argv) {
    13. std::cerr << "main thread: " << QThread::currentThreadId() << std::endl;
    14.  
    15. QApplication app(argc, argv);
    16. QApplication::postEvent(new Terminator,
    17. new QEvent(QEvent::User));
    18. return app.exec();
    19. }
    To copy to clipboard, switch view to plain text mode 
    A custom event that terminates the application is posted in the main loop. When QApplication::exec is called, the event is processed. Everything works as expected and the output is:

    main thread: 140735005136720
    Terminator::event

    But if the event is posted in a different thread, it will not be handled. Here's a minimal thread class and accordingly adjusted main function:
    Qt Code:
    1. struct MyThread : QThread {
    2. void run() {
    3. std::cerr << "MyThread: " << currentThreadId() << std::endl;
    4.  
    5. QApplication::postEvent(new Terminator,
    6. new QEvent(QEvent::User));
    7. }
    8. };
    9.  
    10. int main(int argc, char** argv) {
    11. std::cerr << "main thread: " << QThread::currentThreadId() << std::endl;
    12.  
    13. QApplication app(argc, argv);
    14.  
    15. MyThread mt;
    16. mt.start();
    17.  
    18. return app.exec();
    19. }
    To copy to clipboard, switch view to plain text mode 
    The output of the program is:

    main thread: 139728441435984
    MyThread: 1099274576

    which means that Terminator::event is never called.

    The system is a standard Fedora (2.6.27.5-41.fc9.x86_64) with pthreads. Everything worked in Qt 3, so somewhere along the way something has changed. Any clues?

  2. #2
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: postEvent and multithreading

    In the latter case Terminator is created in MyThread context. Thus Terminator lives in MyThread and receives events from the event loop of MyThread. But the pitfall is that your MyThread does not run an event loop. The receiving thread must run an event loop. See QThread::exec() for more details.
    J-P Nurmi

  3. #3
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: postEvent and multithreading

    I think the Terminator object is created in the thread's context and the event is somehow transferred to the (not running) event loop of the thread that the event-receiver belongs to (in which case it would never get processed).

    from the docs (threads)
    A QObject instance is said to live in the thread in which it is created. Events to that object are dispatched by that thread's event loop. The thread in which a QObject lives is available using QObject::thread().
    Maybe it works if you create the terminator-object as a global.

    HTH

  4. The following user says thank you to caduel for this useful post:

    Thymson (22nd December 2008)

  5. #4
    Join Date
    Dec 2008
    Posts
    3
    Thanks
    1

    Default Re: postEvent and multithreading

    Quote Originally Posted by caduel View Post
    I think the Terminator object is created in the thread's context and the event is somehow transferred to the (not running) event loop of the thread that the event-receiver belongs to (in which case it would never get processed).

    from the docs (threads)

    Maybe it works if you create the terminator-object as a global.

    HTH
    You're right! That works. Thanks!

  6. #5
    Join Date
    Dec 2008
    Posts
    3
    Thanks
    1

    Default Re: postEvent and multithreading

    It also worked to change the thread "affinity".
    Qt Code:
    1. Terminator* t1 = new Terminator;
    2. t1->moveToThread(QApplication::instance()->thread());
    3. QApplication::postEvent(t1, new QEvent(QEvent::User));
    To copy to clipboard, switch view to plain text mode 

    And that solves my specific problem.

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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.