Results 1 to 18 of 18

Thread: Non-Gui thread blocking gui

  1. #1
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Non-Gui thread blocking gui

    The following code is a slot. When calling it using a signal from an object running in the GUI thread, the GUI blocks until the slot is finished executing. Which is a bit strange, because this code is running in it's own thread, so it shouldn't do that, right?
    Also, it blocks until timeWaited == timeout*1000 (10 seconds in this case ) which it shouldn't, because the moment the thread connects to the server it changes the state of st into CONNECTED or LOGGED_IN. So obviously something is going wrong, but since this is my first time ever using threads I'm a bit lost.

    Qt Code:
    1. void Connection::deferredWriteCommand( const QString& command )
    2. {
    3. if( !isRunning() ){
    4. start();
    5. }
    6. bool done = false;
    7. int timeWaited = 0;
    8. while( !done && timeWaited < timeout*1000 ){
    9. switch( st ){
    10. case DISCONNECTED:
    11. wait( 1000 );
    12. timeWaited += 1000;
    13. break;
    14. case CONNECTED:
    15. if( parent->getAuthorization() ){
    16. wait( 1000 );
    17. timeWaited += 1000;
    18. }else{
    19. socket->write( command.toLatin1(), (quint64) command.length() );
    20. socket->flush();
    21. done = true;
    22. }
    23. break;
    24. case LOGGED_IN:
    25. socket->write( command.toLatin1(), (quint64) command.length() );
    26. socket->flush();
    27. done = true;
    28. break;
    29. default:
    30. break;
    31. };
    32. if( done ){
    33. break;
    34. }
    35. }
    36. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    What is this Connection class? Subclass of QThread? If so, then you're doing a strange thing here:
    Qt Code:
    1. if( !isRunning() ){
    2. start();
    3. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Non-Gui thread blocking gui

    Yes, it's a sublass of QThread. You're not allowed to run it from itself? Well, that never gets called anyway, since the code that starts the thread is called from another class, and looks like this :

    Qt Code:
    1. if( !server.at( index )->connection( i )->isRunning() ){
    2. server.at( index )->connection( i )->start( QThread::NormalPriority );
    3. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    Quote Originally Posted by Valheru View Post
    You're not allowed to run it from itself?
    It's not that you're not allowed. It just doesn't make sense to do so, because to trigger a slot, you need an event loop running, so if you run the loop from within a slot, the loop must be already running, because the slot was triggered.

    In your case there are two possibilities - either the block occurs because you did something in the main thread or the slot is called in the context of the main thread (instead of the worker thread) which obviously blocks its event loop. Are you sure the slot is run from the worker thread? Could you show us the connect statement for that slot?

  5. #5
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Non-Gui thread blocking gui

    Qt Code:
    1. void Server::fetchGroups()
    2. {
    3. //emit emitLogData( "fetchGroups() called" );
    4. bool done = false;
    5. for( int i = 0; i < getNumberConnections(); i++ ){
    6. switch( connections.at( i )->state() ){
    7. case Connection::CONNECTED:
    8. //emit emitLogData( QString( "Connection %1 state = CONNECTED" ).arg( i ) );
    9. disconnect( this, SIGNAL( emitDeferredWriteCommand( const QString& ) ) );
    10. connect( this, SIGNAL( emitDeferredWriteCommand( const QString& ) ),
    11. connections.at( i ), SLOT( deferredWriteCommand( const QString& ) ) );
    12. emit emitDeferredWriteCommand( "LIST\r\n" );
    13. done = true;
    14. break;
    15. case Connection::DISCONNECTED:
    16. //emit emitLogData( QString( "Connection %1 state = DISCONNECTED" ).arg( i ) );
    17. addServerTab();
    18. connections.at( i )->start( QThread::NormalPriority );
    19. disconnect( this, SIGNAL( emitDeferredWriteCommand( const QString& ) ) );
    20. connect( this, SIGNAL( emitDeferredWriteCommand( const QString& ) ),
    21. connections.at( i ), SLOT( deferredWriteCommand( const QString& ) ) );
    22. emit emitDeferredWriteCommand( "LIST\r\n" );
    23. done = true;
    24. break;
    25. case Connection::LOGGED_IN:
    26. //emit emitLogData( QString( "Connection %1 state = LOGGED_IN" ).arg( i ) );
    27. connections.at( i )->writeCommand("LIST\r\n");
    28. done = true;
    29. break;
    30. case Connection::LISTING_GROUPS:
    31. break;
    32. default:
    33. emit emitLogData("No available connections" );
    34. break;
    35. };
    36. if( done ){
    37. //emit emitLogData( QString( "Connection %1 found" ).arg( i ) );
    38. break;
    39. }
    40. }
    41. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    Hmm... very strange... Why don't you use custom events instead of such a complicated and strange design?

    Qt Code:
    1. const int MyCustomEventNum = QEvent::User+1;
    2. class MyCustomEvent : public QEvent {
    3. MyCustomEvent(const QString &comm) : QEvent(MyCustomEventNum){
    4. _comm = comm;
    5. }
    6. const QString &command() const { return _comm; }
    7. private:
    8. QString _comm;
    9. };
    10. void Connection::customEvent(QEvent *e){
    11. if(e->type()==MyCustomEventNum){
    12. doSomething(((MyCustomEvent*)e)->command());
    13. }
    14. }
    To copy to clipboard, switch view to plain text mode 
    and in your code:
    Qt Code:
    1. case Connection::CONNECTED:
    2. QCoreApplication::postEvent(connections.at( i ), new MyCustomEvent("LIST\r\n"));
    3. break;
    To copy to clipboard, switch view to plain text mode 

  7. #7
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Non-Gui thread blocking gui

    Well, the reason for this is because the user could concievably call fetchGroups() before connecting to the server. In this case, the first available Connection should connect to the server before issuing the command to the NNTP server. This is why I created a slot in the Connection class that does just that. What is confusing me is that although every Connection runs in it's own thread, and doesn't block the GUI while it's doing other things, it does block the GUI when doing this one thing.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    You could try explicitely calling connect with the additional parameter Qt::QueuedConnection, but I still think using custom events would be simpler, quicker and nicer.

  9. #9
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Non-Gui thread blocking gui

    Heh, I just tried it as a queuedconnection and you're right - it didn't help I've just been looking at the docs for the custom event, I didn't even know that they existed - thanks for the tip. I'll try that now.

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    It may behave incorrectly because you are emitting the signal to the thread object. And the thread object lives in the same thread as the calling object (only objects created within run() or from within methods called from the thread's event loop live in the worker thread), so the slot might be called by the wrong (main) thread. It could be possible that all you need to do is to wait until the thread is started before emitting the signal (but you have to explicitely use queued connections for that to work!) - that would explain why subsequent signals work correctly.

    Qt Code:
    1. connections.at( i )->start( QThread::NormalPriority );
    2. while(!connections.at(i)->isRunning()) QThread::sleep(100); //crude, but should work
    To copy to clipboard, switch view to plain text mode 

  11. #11
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Non-Gui thread blocking gui

    Would the custom event run in the worker thread? I'd prefer to do it that way if it is so, I'm busy restructuring the program now to make it cleaner and fix bugs so I don't want to hack some half-assed fix in if at all possible

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    Quote Originally Posted by Valheru View Post
    Would the custom event run in the worker thread?
    Yes, but with the same condition - make sure the thread is already running its event queue (as this probably moves the thread object to the thread itself) before posting the first event.

  13. #13
    Join Date
    Aug 2006
    Posts
    163
    Thanks
    12
    Thanked 5 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Non-Gui thread blocking gui

    Hmm, it doesn't seem to like being passed an int as argument for the creator of QEvent. Would it be safe to statically cast it to QEvent::Type?

    Qt Code:
    1. connection.h:35: error: invalid conversion from ‘int’ to ‘QEvent::Type’
    To copy to clipboard, switch view to plain text mode 

  14. #14
    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: Non-Gui thread blocking gui

    In Qt 4, a slot in a QThread subclass ends up being executed in the thread where the QThread object itself is living in (QObject lives in the thread where it was created).

    A signal and slot connection is direct between objects living in the same thread. So if a QThread object is instantiated in the main GUI thread, the QThread object itself also lives in the main GUI thread. And so the connection is direct and the slot in a QThread subclass ends up being executed in the main GUI thread aswell.

    You can avoid all this by simply creating a QObject in QThread::run() and connecting signals to that object instead of the QThread object. This ensures that the signal slot connection is across thread.
    Attached Files Attached Files
    J-P Nurmi

  15. #15
    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: Non-Gui thread blocking gui

    The behaviour is exactly the same with posting events. The event gets processed in the event loop running in the thread where the receiver object lives in. Since the QThread object lives in the main thread, it's customEvent() gets executed in the main thread as well.
    Attached Files Attached Files
    J-P Nurmi

  16. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Non-Gui thread blocking gui

    Quote Originally Posted by Valheru View Post
    Hmm, it doesn't seem to like being passed an int as argument for the creator of QEvent. Would it be safe to statically cast it to QEvent::Type?
    Yes.

    Quote Originally Posted by jpn View Post
    The behaviour is exactly the same with posting events. The event gets processed in the event loop running in the thread where the receiver object lives in. Since the QThread object lives in the main thread, it's customEvent() gets executed in the main thread as well.
    Hmm... I thought exec() moves the object into the thread. If it doesn't, it should be enough to move it inside run():

    Qt Code:
    1. void MyThread::run(){
    2. moveToThread(this);
    3. exec();
    4. }
    To copy to clipboard, switch view to plain text mode 

  17. #17
    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: Non-Gui thread blocking gui

    Quote Originally Posted by wysota View Post
    Hmm... I thought exec() moves the object into the thread. If it doesn't, it should be enough to move it inside run():

    Qt Code:
    1. void MyThread::run(){
    2. moveToThread(this);
    3. exec();
    4. }
    To copy to clipboard, switch view to plain text mode 
    Good idea, but seems to be not possible:
    QObject::moveToThread: Current thread (003E7CA0) is not the object's thread (0012FEC4).
    Cannot move to target thread (0012FEC4)
    I tested with both
    Qt Code:
    1. moveToThread(this);
    2. // and
    3. moveToThread(QThread::currentThread());
    To copy to clipboard, switch view to plain text mode 
    J-P Nurmi

  18. #18
    Join Date
    Feb 2010
    Posts
    3

    Default Re: Non-Gui thread blocking gui

    Quote Originally Posted by jpn View Post
    Good idea, but seems to be not possible:


    I tested with both
    Qt Code:
    1. moveToThread(this);
    2. // and
    3. moveToThread(QThread::currentThread());
    To copy to clipboard, switch view to plain text mode 
    I had the same problem, but when you call "moveToThread" in the class' constructor (which is executed in the thread the object is created in), it seems to work.

Similar Threads

  1. simple thread layout question
    By mhoover in forum Qt Programming
    Replies: 1
    Last Post: 12th August 2006, 11:02
  2. Replies: 11
    Last Post: 7th July 2006, 13:09
  3. [QT4] QThread and printing a QList<QPixmap>
    By KShots in forum Qt Programming
    Replies: 3
    Last Post: 24th April 2006, 21:44
  4. Problem building Qt4.1.0 with thread support on windows XP
    By pavithra in forum Installation and Deployment
    Replies: 1
    Last Post: 1st April 2006, 11:35
  5. Replies: 2
    Last Post: 6th January 2006, 21:15

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.