[SOLVED] About signals and slots timing..
-
Hi everybody..
I'm developing an application using Qt and I need some advices signals/slots related.. I have a method that reads an XML file and extracts data from it, but the file must have the correct start tag to be readed (it must be valid). As there could be some not saved data in the form, I would like to clear the current data only when I'm sure the file to read is valid. I was reading about callbacks, but it gets a little tricky as the method I want to call is part of a class (and non static). I want to avoid wrappers as they look a bit dirty, so I thought signals/slots could do a good job (my current method for reading the file is static, but I could adapt it).
The documentation says "When a signal is emitted, the slots connected to it are usually executed immediately" (I'm using direct connection), but that "usually" makes me doubt.. As the read method would insert data just after the signal is emitted, I need to be sure the clear slot associated to the signal is called before the code following the "emit" keyword is executed. So my question is: Will the clear method be completed before the read method continues? (always).
Thanks for reading!
Greetings
-
The default value for the connection type ConnectionType is AutoConnection.
However, you may choose also DirectConnection.
The documentation sais:
@
Qt::DirectConnection 1 The slot is invoked immediately, when the signal is emitted.
@In my opinion the usually has to be seen when you do not specify ConnectionType and the default value is used.
-
As the signal is emitted in the same thread as the recieving object, Qt::AutoConnection will assign Qt::DirectConnection. In simple words, I would like to know if the code after the "emit" keyword will be executed (always) after every slot associated with the signal is called and finished. This is because otherwise my clear slot would delete the data that the read method is adding.
Thanks for your answer.
Greetings!
-
I agree with koahnig on this.
However, note that from the standpoint of the design of the classes with the signals and the slots, you have no control over how they are connected. That means that in your situation, your class emitting the signal cannot know when the signal will be handled, or even if it will be handled at all. It is not wise from a design perspective to rely on the way signals are handled. The whole point of signals and slots is to decouple the objects. If you rely on a certain order or way of handling signals, then you introduce a strong coupling between your objects. There are better patterns around that model this requirement much better than a signal-slot connection.
-
Thanks for your answer!
Could you give me some advices or examples of that better patterns to read about them, please?
Greetings!
-
[quote author="Danielc" date="1322495509"]I need to be sure the clear slot associated to the signal is called before the code following the "emit" keyword is executed. So my question is: Will the clear method be completed before the read method continues? (always).
[/quote]
I'm not sure to understand right your problem, however signals and slots are asynchronous notification mechanism, that can be compared to an event base mechanism. If you need to execute some code before proceeding you need a synchronous way of handling such code, so for instance you need to manually invoke the slot (i.e., a method) in your execution flow. Another way of executing would require locking, but this can overload your application (locking a single thread sounds a little crazy): an an example place a variable as false before the signal emitting; then set to true at the end of the slot and just after the emit lock until the variable is turned (basically a mutex). This is just an example, but I guess that for a single thread application it is too much.
-
I hope this explains my problem better
@void FormClass::clearSlot() {
clearAllForm();
deleteCurrentData();
}static void SomeClass::readFile(QString fileName) {
if(isValidFile(fileName)) {
//It is safe to delete all current data in the form
emit fileValidated;// I need to do this after the current data is deleted because otherwise I would delete the data that is being added // --Code that reads the data from the file and adds it to the form--
}
}
FormClass::FormClass() {
// var is a pointer to SomeClass
connect(var, SIGNAL(fileValidated()), this, SLOT(clearSlot()));
}@(Of course, it is not the real code, but I hope it explains better)
Probably the best I can do is to use callbacks, but then I would need to create two methods (a wrapper and the clear method). Is there a better way to achieve what I want to do?
Greetings!
-
You will need a lock if you don't want to use callbacks. You are trying to solve a synchronou problem with an async solution.
-
[quote author="Danielc" date="1322497747"]Thanks for your answer!
Could you give me some advices or examples of that better patterns to read about them, please?
Greetings![/quote]
A straight forward approach would be to pass a pointer of the external object to your class (e.g. in the constructor or by means of a setter) and call the method directly.
-
Hi again and thanks for the answers.
I will try to implement your suggestion Volker.. I already have something similar but I hadn't thought I could use it.
Thanks!