PDA

View Full Version : Signal/Slot execution sequences/preemption



xenome
17th September 2009, 17:15
Hi,

I have a widget that has a GraphicsScene and a QScrollBar. I have overloaded the widget's resizeEvent() function and connected the QScrollBar's sliderMove() to a custom slot. Each of these routines contains a function call that redraws the objects in my scene. I have found that if the SliderMove() slot executes while I am currently redrawing the scene it will "preempt" my first draw routine with it's call to the draw routine. It was my understanding that the slots would execute to completion (assuming you're not using threads) before another slot is allowed to execute.

Example sequencing.

Resize Event
Start Draw...
SliderMove
Start Draw...
Draw Complete.
Draw Complete.

xenome
17th September 2009, 17:17
I'm sorry, I meant to say I connected a custom slot to the QScrollBar's valueChanged() signal. My custom slot is called SliderMoved().

elmo
17th September 2009, 17:30
From Qt docs (http://doc.trolltech.com/4.5/threads.html#signals-and-slots-across-threads):
Qt supports three types of signal-slot connections:

With direct connections, the slot gets called immediately when the signal is emitted. The slot is executed in the thread that emitted the signal (which is not necessarily the thread where the receiver object lives).
With queued connections, the slot is invoked when control returns to the event loop of the thread to which the object belongs. The slot is executed in the thread where the receiver object lives.
With auto connections (the default), the behavior is the same as with direct connections if the signal is emitted in the thread where the receiver lives; otherwise, the behavior is that of a queued connection.

So changing your connection type to "queued" should do the trick.

xenome
17th September 2009, 19:33
Well I'm not sure that's exactly what I want. Perhaps I don't fully understand how the GUI event loop works, but I would like my first Draw function call to run to completion before the GUI goes on and does other things (which is how i thought it worked with the default sig/slot mechanism). I know that sounds bad; probably not good for a having a responsive interface.

Does the GUI execute and send signals in one thread, but execute slots in a different thread?

I figured it might end up weird having the GUI continue to resize before all the draw functions have completed execution.

wysota
17th September 2009, 20:10
Slots or events will not be disturbed during execution. The effect you obtain has to be caused by some other thread of yours running or a faulty interpretation of results you get. Events and signals are executed synchronously (in the same thread as the object they belong to).

xenome
17th September 2009, 20:29
Well I added Qt::QueuedConnection in the connect() call for the valueChange() signal from the QScrollBar and it appears to have solved the problem.

I'm not quite sure I understand why though....

So the GUI is up and running, I resize it and it fires a resizeEvent which eventually calls my overloaded function which calls my Draw() function. At the same time the scroll bar fires an event saying valueUpdate() because the scroll bar was stretched so it now has a "new" value. That signal is immediately emitted and caught by the slot which also tries to call my Draw() routine.

So now with Queued Connections the valueUpdated() signal is not emitted until the GUI finishes executing the resizeEvent() and essentially goes "idle" ?

If I have my widget (set as the central widget) inside a MainWindow and my QScrollBar is part of the MainWindow's status bar....exactly how many threads do I have running?

wysota
17th September 2009, 20:58
Signal is always emitted immediately... The slot might be called later, if you're using queued connections. But if the latter solves your problems, it means you're using threads in your application. Are you?


If I have my widget (set as the central widget) inside a MainWindow and my QScrollBar is part of the MainWindow's status bar....exactly how many threads do I have running?
If you're not spawning any threads yourself, you should have exactly one thread running.

xenome
17th September 2009, 22:36
Ok, so then I don't understand why does the resizeEvent() function not run to completion before the slot function is processed? I figured everything would have to happen serially. Does QT actually abort event processing to handle an incoming signal? Why is QT processing the QScrollBar signals while it's suppose to be in the middle of processing a resize event?

wysota
17th September 2009, 22:40
Ok, so then I don't understand why does the resizeEvent() function not run to completion before the slot function is processed?
Maybe some signal is emitted from within the event handler?


Does QT actually abort event processing to handle an incoming signal?
No, nothing gets aborted. But if a signal is emitted from within the event, a call will immediately be made to process the signal. When that's done, the event will continue.


Why is QT processing the QScrollBar signals while it's suppose to be in the middle of processing a resize event?
Don't have a clue, that's your program...