Page 2 of 2 FirstFirst 12
Results 21 to 27 of 27

Thread: Thread freezing GUI

  1. #21
    Join Date
    May 2007
    Posts
    90
    Thanks
    40
    Qt products
    Qt4
    Platforms
    Windows

    Smile Re: Thread freezing GUI

    Sorry, I got sidetracked by a memory error and forgot to reply.

    This worked like a charm.

    I really appreciate the help.

    Thank You

  2. #22
    Join Date
    Jan 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread freezing GUI

    Hello all,

    I stumbled across this thread due to having a similar problem. I have read and mostly understood all of this but haven't resolved my GUI freeze. Thank you to all those that have posted and given me a better understanding of some do's and don'ts in Qt. My scenario seems slightly different however.

    I have two versions of this application, Windows and Linux. The Windows version doesn't exhibit the behaviour. The source code is identical between each except for the sound interface. There are roughly 6 threads in each application. The sub threads never freeze or get stuck (I have counters to watch them from a monitor/timer thread.) Even when the GUI freezes the sound can still be heard, Ethernet Packets can be sent and received, the obvious indication of GUI freeze is the buttons will no longer refresh themselves or respond to being pressed, and the Timer SLOT in the GUI thread stops getting called. The Timer SLOT sets a semaphore each time it is called and one of the other threads is released by this semaphore to update all timing operations. The tryAcquire Qt library function times out and posts a message that the timer didn't fire. Once the timer quits firing, it never comes back and the message is printed continuously until the app is shutdown. This occurs somewhat randoming from when the app is started. Sometimes the app never gets fully started, sometimes it runs for long time.

    Sound card is the issue:
    In the Windows version I have two threads for sound. One waits for signals to feed the soundcard samples for playback, and the other waits for signals to grab microphone data. No issues.

    The Linux version uses the ALSA driver. When I don't start the sound driver in the Linux version my GUI doesn't ever seem to freeze. The ALSA version uses the CALLBACK mechanism to know when to move audio. This is where I assume the issue is but I don't quite follow why, or how best to solve it.

    The GUI thread starts the ALSA driver and sets up the CALLBACKS. It had been my assumption that the CALLBACKS were actually executed by lower level (soundcard, kernel, driver level no real clue here) routines, but it may be that by setting up the CALLBACKS from the GUI thread I somehow must interfere with it. I tried creating a separate thread in the Linux version, calling the moveToThread function mentioned previously on it (which I do on all of my threads now thanks to this post), and using it to start up the Linux Sound System. This had the same lack of effect. The ALSA callbacks essentially only interact with a single queue each of sample data each. Other threads handle that data and tickle the GUI as required. I've used this audio mechanism in many other apps with no issues.

    I believe that I have all of the GUI elements properly isolated from the sub threads by signals and slots. The sub threads call public routines that simply emit a signal to cause the GUI thread to change when it can get to it.

    Does anybody have any ideas on this? I have pretty well exhausted my thoughts now other than to rewrite the ALSA routines to not use callbacks and use polling threads for both playback and record similarly to the DirectX version in Windows.

    Thanks to all,
    Doug

  3. #23
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread freezing GUI

    The sub threads call public routines that simply emit a signal to cause the GUI thread to change when it can get to it.
    Do you mean that from a worker thread you call a public method from the GUI thread that emits a signal connected to a slot in the GUI thread?
    Well, here is your problem. The slot from the GUI thread will execute in the worker thread(direct connection). And of course if that slot affects some widgets then you will crash the GUI event loop.
    This is identical with modifying a widget directly from a worker thread.

    So the solution is to emit a signal from the worker thread instead of calling the GUI thread method directly. This signal should be connected to the very same slot that you already have in the GUI thread. The connection will be queued and the slot will execute asynchronously, when the event loop enters.

    Regards

  4. #24
    Join Date
    Jan 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread freezing GUI

    Marcel,

    Over the last couple of days, I have read some additional implementation information on the communication between threads and using the signal/slot mechanism to do this. I follow what you are saying but it seems contradictory with what I have read in the Qt documentation.

    The connect documentation and Qt::AutoConnection state:
    "If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt:irectConnection; otherwise the signal is queued, as with Qt::QueuedConnection."

    By putting both the signal and the slot in the GUI class, calling a member function of the GUI class to emit the signal (and set some variable) from another thread, I should be getting a queue response because the signal is being emitted from a thread which is different from the one where the receiving object is? Am I reading this wrong, that is certainly possible? Just by virtue of the thread in which the SIGNAL is declared, not called, does that change this? Could I also just set these connections up and force them to be queued, since they are unique? My issue is that I would have create these signals and connections in several threads rather than one set of functions in the GUI thread that could be used by all external threads. I can certainly do this, I just want to be sure it is required?

    Beyond that, before I knew anything about not modifying the GUI from non-GUI threads, on the Windows version I got debug messages saying "can't modify xxxx from non-GUI thread." Setting this mechanism up removed the error message, maybe it isn't a fix.

    Further, the Windows version of the app has no problems, only the Linux version does. When I don't run the sound routines in Linux, the GUI doesn't lock up. The GUI does nothing different in this case, I simply don't have audio. I drive the same queues as before at the same rates. Nothing other than normal startup has to occur for my GUI to freeze.

    For other reasons I have been playing with the frequency of the CALLBACKS from ALSA and have noticed that the more frequent the CALLBACKS are occuring, the more quickly my GUI freezes after startup. A 5ms callback rate will freeze within 10 seconds of startup 3 of 5 times. A 10ms callback rate doesn't ever seem to freeze within the first 5 minutes of execution.

    Thus my supposition that the CALLBACKs from ALSA, are causing some issue with the GUI thread. I could very well be wrong and your reply may be my issue. I would like to think that it is since I could solve the problem and move on to other work, but it doesn't quite jive with all the data.

    Please let me know your thoughts and tell me the error of my understanding on the SIGNAL/SLOT multi-thread communications? In addition, can you tell me what thread is getting interrupted by the callbacks from ALSA, or is it none and being executed by the ALSA driver? My intent of the next couple days is to rewrite the ALSA sound routines to be polled from their own threads and see if that helps me.

    Thanks for the thoughts and I look forward to any other advice you can give,
    Doug

  5. #25
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread freezing GUI

    The connect documentation and Qt::AutoConnection state:
    "If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt: DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection."
    Yes, but this connection is made when you call connect, and not derived dynamically, when you emit the signal.

    So the connection remains Qt:: DirectConnection, even if you call the method that emits the signal from another thread.

    By putting both the signal and the slot in the GUI class, calling a member function of the GUI class to emit the signal (and set some variable) from another thread, I should be getting a queue response because the signal is being emitted from a thread which is different from the one where the receiving object is? Am I reading this wrong, that is certainly possible? Just by virtue of the thread in which the SIGNAL is declared, not called, does that change this? Could I also just set these connections up and force them to be queued, since they are unique? My issue is that I would have create these signals and connections in several threads rather than one set of functions in the GUI thread that could be used by all external threads. I can certainly do this, I just want to be sure it is required?
    No, it gets a direct connection. You could try to force it to QueuedConnection when you call connect but I'm not sure if it will work.
    Being a DirectConnection, the slot will get executed in the context of the worker thread.
    So if any widgets are modified as a result of this slot, the GUI will block.

    But why don't you try my suggestion?
    Instead of a GUI method call, just emit a signal from the worker thread. The signal should be connected to the slot in the GUI. There aren't that much modifications to be made( actually they are minimal ).
    This way you are guaranteed to have a QueuedConnection, therefore no blocking.

    I hope you understand.

    For other reasons I have been playing with the frequency of the CALLBACKS from ALSA and have noticed that the more frequent the CALLBACKS are occuring, the more quickly my GUI freezes after startup. A 5ms callback rate will freeze within 10 seconds of startup 3 of 5 times. A 10ms callback rate doesn't ever seem to freeze within the first 5 minutes of execution.
    Yes, a perfectly good explanation for blocking the GUI. Therefore use a signal instead of calling the GUI thread directly. It is not normal to do that.

    Thus my supposition that the CALLBACKs from ALSA, are causing some issue with the GUI thread. I could very well be wrong and your reply may be my issue. I would like to think that it is since I could solve the problem and move on to other work, but it doesn't quite jive with all the data.
    No, only the context in which the GUI slot is executed is the problem.

    Regards
    Last edited by marcel; 24th June 2007 at 17:36.

  6. #26
    Join Date
    Jan 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread freezing GUI

    Thanks Marcel,

    I hadn't thought about it being more about the connect() and when it was done, than when the signal was actually emitted. Basic flaw in my understanding and reading of the documentation.

    I'll give it a try, see what I get, and report back.

    Thanks,
    Doug

  7. #27
    Join Date
    Jan 2007
    Posts
    6
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Thread freezing GUI

    Marcel,

    Before making the changes you suggested, I did a little testing with the debugger. Turns out my method is just fine for creating signals from other threads. In each case that I called one of the public functions in my GUI class to emit the signal, when the GUI update was actually performed it was in fact performed by the GUI thread, not the thread that called the public function causing the signal to be emitted. This was verified in both Windows and Linux.

    I further verified this fact with Trolltech. They stated: "because when the signal is emitted the code in the QMetaObject::activate() will check that the thread that resulted in the emission of the signal is different from the thread in which the object lives. If this is the case, an event will be posted to the event loop of the receiver and will be be processed asynchronously so this is safe."

    In any event, I'm back to square one. I rewrote my ALSA routines to be separate threads (one for playback and one for record) that use blocking calls to move the data. Excactly the same external interface to the rest of my application. No GUI lockups now. Even more surprising is that the audio performance and latency is much better.

    At this point, I'm going to put this on the back burner and expect I'll find the root cause at some point while doing something else. If I do, I'll post on it.

    Thanks for all the suggestions, I certainly learned a lot about some things I didn't know much about before.

    Regards,
    Doug

Similar Threads

  1. KDE/QWT doubt on debian sarge
    By hildebrand in forum KDE Forum
    Replies: 13
    Last Post: 25th April 2007, 06:13
  2. Problem closing a QMainWindow in Qt4.2
    By ian in forum Qt Programming
    Replies: 11
    Last Post: 17th October 2006, 00:49
  3. simple thread layout question
    By mhoover in forum Qt Programming
    Replies: 1
    Last Post: 12th August 2006, 11:02
  4. [QT4] QThread and printing a QList<QPixmap>
    By KShots in forum Qt Programming
    Replies: 3
    Last Post: 24th April 2006, 21:44
  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.