Writing own blocking function



  • Hello,

    I have a little problem and hope you are able to help me: I have a class MyClass containing a function doBlock(bool). The function should be blocking until a result has been created. The result can just be a local member variable or the result from an asynchronous operation by QLocalSocket. The LocalSocket itself is another class, let's call it "MySocket" :)
    But MySocket will only be created if the boolean from doBlock() was set to true.

    Now my problem: The MySocket-Class has SLOTS like readyRead and so on and needs to return a value, when some conditions were fulfilled (the data has been sent completely for example).

    So what I need is an own blocking mechanism to create in doBlock() which not returns a value before the LocalSocket got all data.

    I hope that I could convey my problem. If not, just ask me :)

    Greetings,
    Tom


  • Lifetime Qt Champion

    Hi
    Blocking in a GUI application is never really nice so i wonder if not possible to simply use signal and slots
    so when some conditions are fulfilled, a signal is send and App simply goes on with next step.
    Is there a good reason, you really must block the GUI thread ?



  • As @mrjj aluded to, you don't want to block anything. You just want to check a condition to see if a particular event has succeeded and act accordingly. Lets assume you are waiting for a datagram. You don't block. Connect readyRead to a custom slot that reads the data...verify the event you have been looking for, and either re-imit an application signal to do something, or set a local status variable to show that the event has occured.


  • Moderators

    @stvtdn said in Writing own blocking function:

    The function should be blocking until a result has been created.

    Don't block. Show a modal QProgressDialog instead.



  • Hello,
    thank you for your replies!

    I could implement SIGNAL/SLOTS for this task but I wanted to know, how - for example - "waitForReadyRead" works because it is sometimes a better workflow. If you call the blocking function you are able to proceed in the same context and do not have to implement an extra SLOT for this and comment your source code like "From here it goes on in the slot xyz()".

    The blocking part itself is not a problem. It is running in a worker thread and will not block the GUI thread.


  • Qt Champions 2018


  • Moderators

    @stvtdn said in Writing own blocking function:

    I could implement SIGNAL/SLOTS for this task but I wanted to know, how - for example - "waitForReadyRead" works because it is sometimes a better workflow. If you call the blocking function you are able to proceed in the same context and do not have to implement an extra SLOT for this and comment your source code like "From here it goes on in the slot xyz()".

    The blocking part itself is not a problem. It is running in a worker thread and will not block the GUI thread.

    OK, that makes sense.

    To clarify @jsulm's suggestion: Start a QEventLoop using QEventLoop::exec() in your doBlock() function. This will cause doBlock() to block until you quit the event loop. Connect your socket's readyRead() signal to your data processing slot. In this slot, generate your result and call QEventLoop::quit().


  • Qt Champions 2018

    @stvtdn said in Writing own blocking function:

    waitForReadyRead

    The problem with this is that you can't quit the thread until this function returned which can (and sooner or later will) maybe create troubles.



  • here you have my way of doing it

    void atpTcpSocket::socketReadyRead() {
    
    	qint32 size = *sizeData;
    
    	while (this->bytesAvailable() > 0) {
    		QByteArray sockReadAll = this->readAll();
    		buffer->append(sockReadAll);
    
    		while ((size == 0 && buffer->size() >= 4) || (size > 0 && buffer->size() >= size)) { //While can process data, process it
    
    			if (size == 0 && buffer->size() >= 4) {//if size of data has received completely, then store it on our global variable
    				size = ArrayToInt(buffer->mid(0, 4));
    				*sizeData = size;
    				buffer->remove(0, 4);
    			}
    			if (size > 0 && buffer->size() >= size) {// If data is received completely, then emit our SIGNAL with the data
    				QByteArray data = buffer->mid(0, size);
    				buffer->remove(0, size);
    				size = 0;
    
    				*sizeData = size;
    				emit socketDataReceived(isLoggedIn, connId, userName, data);
    			}
    		}
    	}
    }
    

    hope this help
    I'm using signal end slots system and the GUI is not blocked at any time, also my server is running in thread pool mode with is the best way if you have to handle many connections at a time


  • Qt Champions 2018

    @arsinte_andrei said in Writing own blocking function:

    while (this->bytesAvailable() > 0)

    This is not needed since readyRead() is emitted as soon as there is new data available.



  • Thank you so much for your replies guys!

    As suggested I am now using the QEventLoop which will be quitted by QCoreApplication::quit() instead of emitting a signal.

    A little question to that: I have two event loops now, one in main.cpp and one in my worker class. It looks like that everything is going right but I do not really understand how it works.
    Which event loop will be closed by calling QCoreApplication::quit()? Is it the last one created? In other words, in which context am I working, if I create a new event loop?



  • Ok, that was a stupid question.... My application is quitting now.


  • Qt Champions 2018

    @stvtdn said in Writing own blocking function:

    As suggested I am now using the QEventLoop which will be quitted by QCoreApplication::quit()

    I'm not sure why you want to exit your application when this event loop finishes?
    I thought you wanted a blocking function, which blocks until it's done with its work?
    To terminate your event loop you can connect a signal to https://doc.qt.io/qt-5/qeventloop.html#quit



  • Thank you for your help! Yesterday I had a segmentation fault in my brain...

    I think I got it now: https://pastebin.com/XuadvD9X

    This example timeouts before the signal finished() is emitted. To test the correct way you need to set the timer value higher than the singleShot timeout.


Log in to reply