QEventLoop example...



  • Hello,
    I was going through Qt help documents, in which I read about a class QEventLoop, which says that At any time, you can create a QEventLoop object and call exec() on it to start a local event loop, so from this what I understood is just like the main event loop, which we start at the end of main function [which actually handles all the signal-slot traffic], I can create a local event loop for my specific class and all the signal slots connection will be handled by this local event loop and main event loop will not be troubled.
    Correct me if I am wrong and provide me proper example to utilise it...



  • Hi,

    I already utilize such solution. I had problem with JavaScript inside WebKit "Post WebKit":http://qt-project.org/forums/viewthread/19023/ More info about this and related articles you can find in "this post":http://qt-project.org/forums/viewthread/19241/ There is information about drawback and advantages of such solution.

    Best regards,



  • Thank You... Both links helped me to understand the concept and implementation.

    Now in the post of second "link":http://qt-project.org/forums/viewthread/19241/ it is stated somewhere that,
    [quote author="guziemic" date="1343799659"]Hi,

    I can agree that blocking is not a good approach. But using sleep() in code is not the best solution, as you doing pooling on your own. Better is to take some advantages from Qt and utilize its signals, slots and execution loops.
    I think that you could implement internal event loop that will wait for signal from Network.

    @
    somefunction()
    {
    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
    QEventLoop loop;
    QTimer timer;

    timer.setSingleShot(true);
    connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
    connect(manager, SIGNAL(finished()), &loop, SLOT(quit()));

    timer.start(5000); //your predefined timeout
    manager->get(QNetworkRequest(QUrl("http://google.com")));
    loop.exec();

    if (timer.isActive) //replay received before timer, you can then get replay form network access manager and do whatever you want with it
    else //timer elapsed, no replay from client, ups
    }
    @

    Above do not block whole application. It only creates event loop and 'block' function in which was executed till quit() is called.[/quote]

    so if the function which executed the event loop gets block, obviously, blocks the calling function too, right.???



  • Amazing... :D
    Unlike normal function calls, where calling function gets blocked untill the return of called function and blocks everything, local event loops keeps UI responsive, even if the call is blocked...

    Pretty much thread like behaviour, where thread runs independentaly without blocking whole application...



  • i don't recommend using QEventLoop for serious projects. it makes the application unstable.



  • [quote author="Mohsen" date="1348209778"]i don't recommend using QEventLoop for serious projects. it makes the application unstable.[/quote]

    Can you explain little more with may be some example... It will help...



  • for example, creating a thread and using QEventLoop to block until thread finish; closing the application won't complete process and doesn't clear the process.
    unexpected crashes also blinks ;)



  • Another fine example, is if you have other sources of input for your application than just the mouse and keyboard. Think of DBUS or networking. These methods are also processed in that new eventloop. Are you really prepared to deal with that?

    In general, I think local eventloops outside the context of threads should be avoided. That includes modal dialog boxes started with exec() or the static methods.



  • In one minute I thought QEventLoop will help me out but then I hear it is not recommended.

    My application was working for several weeks and then it started to crash or freeze all the time.
    I found out that problem is connected to QTcpSocket::waitForReadyRead() which is buggy:
    https://bugreports.qt-project.org/browse/QTBUG-24451
    and
    https://bugreports.qt-project.org/browse/QTBUG-14975

    My communication is run synchronously (ModBus RTU protocol) so blocking mechanism in a thread was everything I needed. Without that I need to recode a lot bunch of code to utilize signal/slot approach. Even then Iv got problem to communicate properly, because whenever I send data and wait for signal in a thread ( QWaitCondition::wait(&mutex) ) it never arrives because main loop is blocked.

    Basically when I was using waitReadyRead() the communication looked like this:

    O! I will use pseudocode to make it easier to show how it works

    @
    mainThread
    {
    execModbusCommand(); // <- this starts a new thread but blocks/waits till response is received for a sent message ( waitReadyRead() )
    nextFunctionExecutedAfterExecModbusCommandFinishes();
    }
    @

    This is my new approach which is not working (slot for signal QTcpSocket::readyRead() is not executed) because main event loop is blocked(??):

    @
    mainThread
    {
    execModbusCommand(); // <- this starts a new thread but blocks/waits till response is received for a sent message ( QWaitCondition::wait(&mutex) )
    nextFunctionExecutedAfterExecModbusCommandFinishes();
    }

    execModbusCommandThread1
    {
    QMutex mutex; // declared in header's class - NOT LOCALLY!
    bool ensureSignalToWriteDataIsExecutedBeforeQWaitConditionCheck = true; // declared in header's class - NOT LOCALLY!
    QWaitCondition qwc;

    emit signalTcpSocketWriteData( dataToSend );  // it executes slot in another Thread2
    while( ensureSignalToWriteDataIsExecutedBeforeQWaitConditionCheck )
    {
         boost::posix_time::milliseconds wait(1);
         boost::this_thread::sleep(wait);
    }
    qwc.wait(&mutex);  // it should block till mutex is unlocked in readyReadSlot()
    // after this line we know that signal readyRead() is emitted so we can read the data
    QTcpSocket::readAll();
    

    }

    slotTcpSocketWriteDataThread2 // Iv got whole QTcpSocket put into QThread ( moveToThread() ) so it is run as a another thread
    {
    mutex.lock(); // shared mutex from execModbusCommandThread1
    ensureSignalToWriteDataIsExecutedBeforeQWaitConditionCheck = false;
    QTcpSocket::write();
    }

    slotReadyReadThread2
    {
    qwc.wakeAll(); // shared from execModbusCommandThread1
    // after this is executed function QTcpSocket::readAll() from execModbusCommandThread1 should be started
    // BUT PROGRAM NEVER ARRIVES HERE because execModbusCommandThread1() is waiting in qwc.wait(&mutex) so event loop in mainThread() is blocked?????
    }

    @

    Can you recommend me a good approach to solve issue with waitReadyRead() by proper signal/slot coding?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.