Qt: wait for a signal in synchronously mode

Qt libraries work using the mechanism called signal-slot. Basically this is a optimal way to make an asynchronous communication between objects in any kind of conditions and transmitting any kind of data. However, sometimes, may happen the need to wait for a very short time event (for example wait for the end of a short animation).


In this case could be a little annoying and useless to "break" the flow of the code for manage the asynchronous signal to waiting for. In this case could be better to wait synchronously the signal and using the fantastic Qt is a very easy task as usual.

No need many explanations, just get the following code and put in an header file to add to your project:

class SignalWait
{
    QSignalSpy m_SignalSpy;

public:

    SignalWait(QObject *object, const char *signal) : m_SignalSpy(object, signal) {}

    bool Wait(const int msTimeout)
    {
        QTime Timer(0,0,0,msTimeout);

        Timer.start();

        while(m_SignalSpy.isEmpty() == true && Timer.elapsed() < msTimeout)
        {
            QCoreApplication::processEvents();
        }

        return (!m_SignalSpy.isEmpty());
    }
};

Once included this header in the .cpp code file you need to wait in just use the class as showed below:

SignalWait sw(obj_pointer_generating_signal, SIGNAL(signal_func_name()));

// Here start code generating the signal to wait for 
// ...

if(sw.Wait(1000)) // Wait for max 1 sec
{
   // Signal received
}
else
{
   // Signal not received until timeout
}

As you can see using this class you can also set a timeout for the signal wait and the loop process the other events of the application for not lock other tasks. Please note that this method require to add the SignalSpy Qt library to the project.

An alternative way

A second way to make same task would be to use the QEventLoop class. However be very carefully to use this method only in the main GUI thread since the use in some secondary thread can cause some unknown problems. The QEventLoop basically manage Qt events into the main loop and work as the exec() function of a QDialog class that doesn't return until the close() function is called (the QDialog itself use this class internally). In this case the trick consist to connect the signal you are waiting for to the close (slot) function of the QEventLoop object as following example show:

QEventLoop SignalWaitLoop;

connect(obj_pointer_generating_signal, SIGNAL(signal_func_name()), &SignalWaitLoop, SLOT(quit()));

// Here start code generating the signal to wait for 
// ...

SignalWaitLoop.exec();

// Signal received

Please note this way differ from the first one since it doesn't provide any timeout and it absolutely require the signal to come.

Comments

Popular posts from this blog

Access GPIO from Linux user space

Android: adb push and read-only file system error

Tree in SQL database: The Nested Set Model