[solved] signal/slots -> slot is called too often
-
Short description
I've got a slot (whose job is to show an error in a message box) in my MainWindow class that is called too often from the 2nd time on. The first time an error condition occurs one signal is emitted from another class and the message box is shown once. The second time the signal is emitted once and the box is shown twice. The third time it is shown thrice and so on and so on.
Long description
There is a separate thread (worker thread) that should copy files to a flashdrive. If no further files can be copied (e.g. the flashdrive is full) the signal with the error message is emitted. The worker thread is owned and spawned from a class called USBConnectorClass. It has also a signal that can emit an error message and those two are chained (signal to signal).
The USBConnectorClass is owned by aonther class called DestinationSongsModel which keeps track of the songs on the flashdrive. This one has also a signal to emit error messages and it also chained (signal to signal to signal).
And this signal is connected to the slot in the MainWindow class. (signal to signal to signal to slot)
The separation of those classed is by design, they simply don't know each other (except direct parent/child relation), so the thread can't be connected to the main window directly.debugging so far
Each connection of signal/signal or signal/slot is unique, there are no accidential double connections, that means there is only one place where I can emit the "source" signal. And that signal is emitted only once, be it the first, second or third time (and so on). I've checked that via debugger and and extra qDebug() statement directly before the emitting of the signal.
I've attached a QSignalSpy to the slot and can validate the the count of signals is 1 the first time, 2 the second time and so on. IMHO the documentation is not exactly clear in this point but I guess the count refers to the count of signals at this point in time, when the QSignalSpy is asked (as opposed to count 3 means the slot is called the third time which from my point of view makes no sense at all). On the other hand: if I am doing the third run, the message box is shown thrice and each time the count of the spy shows 3.What other ways are there to debug this signal/slot issue? Is there a way to prove, that the signals have been dequeued after showing the message box? And even if they stay queued, why do they need anther signal to be processed again?
I'm quite sure that I miss something here that somehow specific to my project.
Any kind of help appreciated! :-D (yes, I've digged the forum and this Google thingy before)Platform: Mac OSX 10.7.5, Qt 4.8.3
-
I haven't used QSignalSpy, but maybe it is showing number of slots connected to a singal, not how many times a signal was emited?
Consider this code:
@
connect(this, SIGNAL(signal()), this, SLOT(slot()));
connect(this, SIGNAL(signal()), this, SLOT(slot()));
emit signal();
@
signal will be emitted once, but there will be 2 invocations of slot().From your description it sounds like you connect the same slot again when it is fired, and thus you're getting incremental invocations the next time signal is emitted. You can try to do a disconnect before you call connect to see if that's the case.
-
if you are using function to connect signal something like this:
@
void myFunction(){
connect(this,SIGNAL(someSignal()),this,SLOT(someSlot()));
//some other code
}
@
and you call it multiple times it will be connected multiple times, so if you call 1st time it connects once, but 2nd time it will connect again and you will have 2 connects and 2 times called slot, you can solve it easily by disconnecting the signal/slot before calling myFunction(), for example:
@
if(something){
disconnect(this,SIGNAL(someSignal()),this,SLOT(someSlot()));
myFunction();
}
@ -
[quote author="Krzysztof Kawa" date="1363882835"]I haven't used QSignalSpy, but maybe it is showing number of slots connected to a singal, not how many times a signal was emited?
Consider this code:
@
connect(this, SIGNAL(signal()), this, SLOT(slot()));
connect(this, SIGNAL(signal()), this, SLOT(slot()));
emit signal();
@
signal will be emitted once, but there will be 2 invocations of slot().From your description it sounds like you connect the same slot again when it is fired, and thus you're getting incremental invocations the next time signal is emitted. You can try to do a disconnect before you call connect to see if that's the case.[/quote]
Well, I looked up the code several times and would say for now that I connect only once (only at one place). And if that would be the answer, the slot should be called consistent number of times. Like 2 connections = 2 calls. Except SetBetterPass is right.
-
[quote author="SetBetterPass" date="1363893024"]if you are using function to connect signal something like this:
@
void myFunction(){
connect(this,SIGNAL(someSignal()),this,SLOT(someSlot()));
//some other code
}
@
and you call it multiple times it will be connected multiple times, so if you call 1st time it connects once, but 2nd time it will connect again and you will have 2 connects and 2 times called slot, you can solve it easily by disconnecting the signal/slot before calling myFunction(), for example:
@
if(something){
disconnect(this,SIGNAL(someSignal()),this,SLOT(someSlot()));
myFunction();
}
@[/quote]This could be the answer, because the worker thread is connected each time it is created. On the other hand it is destroyed after it has done its job. AFAIK the connected signal gets removed then. Or must I remove them in the destructor for myself? (Will try this tomorrow)
-
@SetBetterPas
Thank you for changing my perspective, I didn't see the wood for all the trees.
Yes, there was one signal in the middle of the chain connected every time the copy process was set up.@Krzysztof Kawa
I've connected one signal 4 times just to see what happens to the spy: the count went 1,2,3,4 for every subsequent call. So it's not the number of connected signals, we see the number of calls. -
Note that there is a variant of QObject::connect that you can use to prevent the multiple connections, even if you make the connect call multiple times:
@
//no connections at this point
connect(this, SIGNAL(someSignal()), this, SLOT(someSlot()), Qt::uniqueConnection); //ok, returns true
connect(this, SIGNAL(someSignal()), this, SLOT(someSlot()), Qt::uniqueConnection); //returns false, still only one connection
@