I can not find anywhere in the Qt 5.7 documentation of signals and slots if they can be used as a "replacement" for the Producer-Consumer problem.
On a thread, data is constantly being generated and the second thread catches all this data, use it and save the result in a text file. Is it safe to use Signals/Slots here with Qt:QueuedConnection where it is really important to process data in same order as they come.
How does Qt deal with this kind of connection internally?
Qt signals and slots are usually thread safe to use. I'm pretty sure there is a good documentation about it, try this: http://doc.qt.io/qt-5.7/signalsandslots.html and here for for more info about thread interconnectivity with sigals and slots: http://doc.qt.io/qt-5.7/threads-qobject.html#signals-and-slots-across-threads
Related
I have written a C++ 11 code using asio to send/receive the packets from network. To work with asio, asio::io_service::run() need to be called and the main thread will be waiting in this function.
Now, in one of the applications, I need to develop a Gui for which I need to use Qt 4.8. But for a Qt Gui application, the main thread need to wait in QApplication::exec(). Though Qt has its own libraries to send/receive data from Network, I would like to use the code with asio.
How can I use asio along with Qt?
Without seeing your code.. a high-level generic approach:
Call io_context::run() in a new thread. All async handlers will execute in this thread.
Use a mutex to ensure the data model can be safely shared between ASIO and the GUI. Lock the mutex consistently any time the data is read or updated.
Use Qt signals and slots and/or condition_variable to signal the GUI from ASIO completion handlers whenever the UI needs to be updated. Do not touch the GUI directly from ASIO code, as only the UI thread may update the UI.
Writing a cross platform app using Qt (including Windows with MinGW). For reading data from SSL socket, I am creating a separate thread. This thread is there for historical reason, because earlier the app was written using C socket/ssl/crypto libraries. Now all these are being replaced with Qt Network library.
For blocking thread, waitForReadyRead(milliseconds) seems a better choice. Now according to Qt hierarchy:
QIODevice
|
QAbstractSocket
|
QTcpSocket
|
QSslSocket
Documentation of QAbscractSocket::waitForReadyRead() suggests:
Note: This function may fail randomly on Windows. Consider using the event loop and the readyRead() signal if your software will run on Windows.
But the similar warning is Not mentioned in the QIODevice::waitForReadyRead().
Question: Is QSslSocket::waitForReadyRead() consistently usable for all the platforms?
Why am I not using readyRead() signal?
For some strange reason, if I slot some method with readyRead() then it's not getting called. Moreover, the QSslSocket::write() also doesn't work, which works otherwise with above approach. Due to complexity of my code, I am unable to present it here.
To your question: yes you can use QSslSocket::waitForReadyRead() but on Widows it can timeout even when the data came to the socket. So if timeout occurs you have to check if it is timeout or the method failed. The check is simple just if QAbstractSocket::bytesAvailable() > 0 then data are ready for read otherwise it's timeout.
This approach is ok when you use small timeout and your application isn't sensitive on delay (e.g. communication between temperature sensor and cloud with temperature history). But if any unnecessary delay is not acceptable for you then you should use the signal/slot interface.
For more information you can look at the bug report on the Qt's bug tracker.
according to your question.
The implementation of QIODevice does nothing but return false. So there is no need for the hint of sometimes failing.
The implementation of QAbstractSocket calls something called "nativeSelect" internally, which is then directed to the corresponding method, depending on the OS you are running on. For Windows the select implementation sometimes seem to return a negative false.
But this should not harm you, because you should get the hint for available data from your next call to waitForReadyRead().
QSslSocket's waitForReadyRead() internaly uses QAbstactSocket's implementation appart from some SSL checks.
Regarding your problem with the signals and slots.
A mistake, I made when I was new to Qt was, that I tried to signals before I started a MainLoop by calling QApplication::exec() or something else.
The signal slot mechanism does not work without a run loop.
Hope you can get some hints from this.
Regards
Problem might be use resources.
When you will use waitForReady* you creating constraint one socket per one thread (otherwise you will have strange bugs).
Now question is how many sockets do you have? If it depends it on run time data, you may do not know that.
Some embedded systems have limit on number of treads what can impact your application and IMO this is only limit which can impact such implementation.
This part of your question:
Why am I not using readyRead() signal? For some strange reason, if I
slot some method with readyRead() then it's not getting called.
Moreover, the QSslSocket::write() also doesn't work, which works
otherwise with above approach. Due to complexity of my code, I am
unable to present it here.
Looks suspicious.
I never seen someone had similar problem. Maybe some parts of your code is blocking an event loop?
Though it's not an exact answer to the Qn, I am posting a possible implementation of waitForReadyRead(), which can be used under a local event loop.
class MySslSocket : QSslSocket
{
Q_OBJECT
public:
virtual
bool
waitForReadyRead (int milliseconds) override final
{
QEventLoop eventLoop;
QTimer timer;
connect(this, SIGNAL(readyRead()), &eventLoop, SLOT(quit()));
connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
timer.setSingleShot(true);
timer.start(milliseconds);
eventLoop.exec();
return timer.isActive();
}
};
This can be either use exclusively for Windows, or it can be used in general for all platforms.
the application I'm trying to design with Qt is quite data intensive; it is essentially a database. I'm looking for a design that would allow me to keep the UI reactive. My guess is I should keep only the UI in the main thread and create a thread for the database.
However:
- creating a database object inheriting from QThread doesn't seem to be a natural design (what would run() be? )
- I assume I would need to use signals and slots for UI / core interaction; yet this feature seem to be relatively recent in Qt, so I'm wondering if my "design" is wrong.
- QObject descendants are apparently designed to live in the thread in which they were created, so I'm concerned the communication of models (from the database thread) to the UI thread will be problematic.
Thanks for your comments.
You might consider using QtConcurrent::run(). You'll pass in the function you want. It'll spool off a thread to run the function and give you a QFuture that you can use to get the eventual result. You could poll the QFuture to see if it isFinished(). Better, however, may be to use QFutureWatcher which watches the QFuture for you and emits a signal when it's done. See the example code blurb in QFutureWatcher.
Well, I think creating a separate thread for the DB stuff is a good idea... but I would suggest that you only make 1 thread for the DB stuff (not 2, 4, or more). The reason is that unless you are an expert at DB concurrency issues and the locking mechanisms of your DB, things will get complicated.
The thing is that you should not have any other threads mixed with code that has gui or in main of a gui project because any blocking will freeze the GUI as well. So as long as you make a separate DB handler class and thread that, I think you should be OK.
Once I asked that same question "Is this design good?" (after detail explanation), the answer I got is "when doing a design of something, only the sky is the limit".
If you think threads might cause problems, then you should start processes, instead of threads.
Don't forget that you can always block and disable widgets when doing some intensive computation (a famous hourglass icon).
Signals and slots are implementation of observer pattern. In my opinion, it is one of the very useful design patterns. It allows you to easily break dependencies. If you don't like signal slots, then take a look into events.
EDIT
For processes, you can use IPC (inter process communication) - not necessarily using stdout. There are pipes, shared memory and messages.
As for freezing the widgets, you can disable them, or the mouse (turning it into a hourglass) when your application is doing some computation intensive operation, and when you think the GUI might become unresponsive. Or, you can show the invisible widget covering your GUI and change the mouse into the hourglass. This way the mouse events would go to the invisible widget and ignored. You can also add "please wait" box on top of it.
You didn't say what exactly you are trying to achieve. Maybe there is a better way.
I have a Qt/C++ application, with the usual GUI thread, and a network thread. The network thread is using an external library, which has its own select() based event loop... so the network thread isn't using Qt's event system.
At the moment, the network thread just emit()s signals when various events occur, such as a successful connection. I think this works okay, as the signals/slots mechanism posts the signals correctly for the GUI thread.
Now, I need for the network thread to be able to call the GUI thread to ask questions. For example, the network thread may require the GUI thread to request put up a dialog, to request a password.
Does anyone know a suitable mechanism for doing this?
My current best idea is to have the network thread wait using a QWaitCondition, after emitting an object (emit passwordRequestedEvent(passwordRequest);. The passwordRequest object would have a handle on the particular QWaitCondition, and so can signal it when a decision has been made..
Is this sort of thing sensible? or is there another option?
Using signals to send messages between threads is fine, if you don't like using the Condition Variable, then you can send signals in both directions in a more-or-less asynchronous manner: this might be a better option if you want to continue processing network stuff while you wait for a reply from the GUI.
I'm developing an application that gets large images from an Internet server which is the best way to download this images, without freeze the entire application? I mean background download. I have thought about download it in another thread.
Yes, you need to spawn another thread to do the network communication, and then when it is finished doing it's reading, you can use a volatile boolean flag to indicate that the work is complete and the main/application thread can take the data and incorporate it. The data may be "part" of an image if you want to show the image coming in piece by piece (as a browser does).
A background thread will work, but it's tricky to get right and not usually necessary... Qt4 makes it very easy to do non-blocking I/O in the main thread using the QTcpSocket class -- basically you connect the QTcpSocket object's readReady() signal to a slot it your program, and have your slot read out the newly available data from the QTcpSocket when it is called. For an example, have a look at the fortuneclient example in the Qt examples directory ($QTDIR/examples/network/fortuneclient).