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...
-
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-14975My 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?