This question concerns the QSerialPort Library from Qt, but has actually arisen from PySide6 in Python, hence I tagged both.
According to the QSerialPort Documentation, it is possible to have a signal emitted every time new data is available on e.g. the serial port:
https://doc.qt.io/qt-6/qiodevice.html#readyRead
Since I did not find any event based serial port library for C++ (or python), I'm quite sceptical if they are using an event based approach for emitting the signal or rather internally polling until data is available.
I already checked out the documentation and internet and source code, but I could only find the readNotification function for the Unix-Implementation in qiodevice.cpp, which emits the readyRead signal. However, I could not find in which context the function is called, so it's still unclear for me.
According to this answer for a "readyRad-Question" it looks like Qt is using internally the API of the OS (but still supposition).
QSocketnotifier does not work on windows for serialport reading?
Related
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.
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
i read data from RS232 in a for loop.this has no good performance.i want don't have a for loop instead of that there was a thing like event that when data is receiving it fire. is this possible? for example when data is receiving from COM16 event firing.
It looks like this project is being added into Qt 5.1 already in Qt 5!
http://qt-project.org/wiki/QtSerialPort
http://doc-snapshot.qt-project.org/qt5-stable/qtserialport/qtserialport-index.html
The examples show two different ways to get the information out of the Serial port:
This one uses a signal slot connection:
http://doc-snapshot.qt-project.org/qt5-stable/qtserialport/terminal.html
This one uses polling in a loop:
http://doc-snapshot.qt-project.org/qt5-stable/qtserialport/blockingslave.html
This is a different one, but can do all the same things. I've used this one before with success. It has a signal slot available in the examples.
https://code.google.com/p/qextserialport/
Hope that helps.
I am trying to make use of Borlands TClientSocket component in non-blocking mode inside a multithreaded C++ Windows application. I am creating multiple threads (classes derived from TThread), each of which creates its own TClientSocket object. I then assign member functions of the thread class to act as event handlers for the OnConnect, OnDisconnect and OnSocketError events of the socket. The problem I am having here is that whenever I call the TClientSocket::Open() function from within the TThread::Execute() function, the OnConnect event never fires. However, When I call the Open() function from the VCL thread prior to the TThread::Execute() function getting called, all of the events fire and I can use the thread-socket combination as I would like. Now I have not read anything in documentation that says that TClientSocket should not be used in non-blocking mode when used inside a thread, but it appears to me that there is perhaps something wrong conceptually in the way I am trying to use this class. Borland documentation is quite poor on the subject and these components have now been deprecated so reliable information is hard to come by. Despite being deprecated I have to use them as there is no alternative in the Builder 6 package I have. Can anyone please advise me if there is a right/wrong way to use TThread and a non-blocking TClientSocket in combination. I have never had problems using it as part of the VCL thread and never had problems using TServerSocket before and I really cannot understand why some events are not firing.
TClientSocket in non-blocking mode uses a hidden window internally to receive socket events. If you use a non-blocking TClientSocket in a TThread then you must implement a message loop inside of your TThread::Execute() method in order to dispatch those messages to the socket's window. Also, being window-based, that also means that the socket messages are sent to the thread that actually creates the socket window, so you have to make sure you are opening the TClientSocket from inside of your TThread::Execute() method.
BTW, BCB6 shipped with Indy 8, which is an alternative. You can also install an up-to-date version of Indy, or even another third-party library like ICS or Synapse.
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).