[Solved] Signal/Slot interrupts member function
Hey all, bit of a newb as a poster here so forgive me if I mess up the posting protocols!
I have a question regarding emit signal and slot receiver:
I have a class running within a thread. In the class I have a state processing function (pass in an event, do stuff, update state), somthing like (this is hand-written because the real code is much larger and will be a bore to read through):
if (state == STATE1)
if (event == EVENT1)
state = STATE2
qDebug() << "Invalid event received in state1\n";
else if (state == STATE2)
if (event == EVENT2)
state = STATE3
qDebug() << "Invalid event received in state 2\n";
During STATE1, EVENT1 I call function doThingThatCallProcessState() which causes various things to occur that triggers a signal that is received in a slot in my class. The slot handing calls processState(EVENTx);, but it calls it before the last processState has finished - i.e. it seems to interrupt my code. For me this means that before an event is fully processed another event interrupts it and is processed before its time and is therefore in the incorrect state.
Does anyone have any good ideas how to tackle such an issue. I would prefer and processState() call to be completely finished before it is called again.
I did have a search for this, but its a difficult topic to explain, so searching was not easy and yielded no results for me.
Thanks very much : )
if you're using emit and QObject::connect you must use Qt::QueuedConnection, "check Qt connection type":http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum
ah ha!.... I think that sounds about right, thanks!
as a work around I had written my own event queue : ((
I'll check it out and report back.
Being multl-threaded, your function might be call by several other threads at any given point in time. You might also be interested by the BlockingQueuedConnection.
Since this looks like a state machine, did you have a look at the "QStateMachine":http://qt-project.org/doc/qt-4.8/qstatemachine.html and friend classes ?
Hope it helps
I would start by outputting QThread::currentThreadId(), and see how many different threads are calling you.
Also, there's no need to explicitly specify QueuedConnection here. AutoConnection recognizes whether sender and receiver are in the same thread.
Thanks all very much for all the feedback
I can confirm that my main issue is solved using the Qt::DirectConnection and Qt::QueuedConnection parameters for the slot/signal connect() function. By using QueuedConnection for local (same thread) signals it stopped them from interrupting me :)
The blocking thing looks useful too, I had a good read of all the options there.
Regarding the state machine, I did look at the QStateMachine class but since my state machine handles my own event types (i.e. not just signals) I could not see how it would work for me (though admittedly I did not spend too much time on that as I have a good template of my own that is nothing like the example I wrote in my first post :o )
I did have serious issues at the start with the QThreads but I am ok with the multi-threadedness (if thats a word) for now, but currentThreadId() was VERY useful when debuggin it : ))
"Also, there’s no need to explicitly specify QueuedConnection here. AutoConnection recognizes whether sender and receiver are in the same thread"
AutoConnection will make a signal emitted to a slot in the same thread "DirectConnection" so you do need to explicitly use this parameter sometimes. Same if you want to make your signal to another thread "immediate" instead of queued...
You have a point, QueuedConnection is sometimes desirable.
However you should not use direct connection explicitly when connecting signals and slots in different threads, because suddenly the slots will be called in the context of the calling thread, leading to all kinds of confusions.