sorry, I can`t be mor speciic, because I am stuck in a jumble of classes, and several signal/slots.
In my project I use several signal-slots. Now I have the impression that depending on how often I start a routine that emits a signal my slot is run several times.
For the first rum my Slot is run once; In the second run it is run twice.... When I close my program I start again with running it once.
Is there a need to somehow finish/end/delete a signal after it is sent ?
Thank you
Take a look to the Qt::UniqueConnection flag.
You're connecting signals to slots in reaction to events. This causes duplicate connections as the events are repeated. In most cases, this is a bug. Usually you want to set up connections in class constructors, or otherwise when new objects are created and added to your system.
The unique connection will mask the problem, but not solve it - the solution is to move the connect statements to locations where they won't be re-executed.
A a signal stays connected, until either the disconnect() is used, or the sender or receiver is deleted.
So each signal/slot pair has to beconnected only once, and then every time the signal is emitted, the slot gets called.
Related
According to following post an emitted signal is served, only once the currently executing slot completes.
Wait for a SLOT to finish the execution with Qt
I have a client-server communication app based on ssl socket, which is single threaded.
connect(socket, &QSslSocket::readyRead, [&]() { myObject.Read(); });
Client & server send each other some custom messages. Whenever a message is sent or received by either, they send ACK bytes (00).
Most of the times, I notice that when the Read() is in between of execution, the next readyRead() is served! I put debug statements in beginning & end of myObject->Read(). They confirm that, beginning debug is called again & again. Same is observed with breakpoints.
When too much of data is received, a recursive stack frame is created of too many Read()s. It either slows down the app GUI or crashes.
Typically this recursion happens, when client attempts to send an ACK as part of myObject->Read(). During that time readyRead() is incidentally signalled & also gets served. However the slot of previous signal was still under processing.
Questions:
Is it possible for Qt framework to cater a signal in between when a slot is still mid-way (single thread)?
How to fix this socket specific scenario?
Note:
- By default for single threads, the Qt::ConnectionType is DirectConnection. I have tried with QueuedConnection as well, but the result is same.
- myObject.Read() is quite complex and has many other function calls. If this is causing problem, then let me know what should I look for. It will be impractical to write the actual code of it.
The recursive calls of readyRead() were happening because of the event loop getting freed up in between. Following functions were causing the event loop to be freed:
QCoreApplication::processEvents()
SslSocket::flush()
The 1st is understandable, as it's meant for that. But the 2nd flush() was a total surprise. Its documentation doesn't state so. At least in my debugging it was showing that, whenever the flush() is invoked, the subsequent readyRead() is invoked and catered. See that in the Qn as well.
The processEvent() was meant to make GUI more responsive during the high loading of the data. But it seems that, we need to make another choice for the same.
I have an ordinary GUI Thread (Main Window) and want to attach a Worker thread to it. The Worker thread will be instantiated, moved to its own thread and then fired away to run on its own independently, running a messaging routine (non-blocking).
This is where the worker is created:
void MainWindow::on_connectButton_clicked()
{
Worker* workwork;
workwork= new Worker();
connect(workwork,SIGNAL(invokeTestResultsUpdate(int,quint8)),
this,SLOT(updateTestResults(int,quint8)),Qt::QueuedConnection);
connect(this,SIGNAL(emitInit()),workwork,SLOT(init()));
workwork->startBC();
}
This is where the Worker starts:
void Worker::startBC()
{
t1553 = new QThread();
this->moveToThread(t1553);
connect(t1553,SIGNAL(started()),this,SLOT(run1553Process()));
t1553->start();
}
I have two problems here, regarding the event queue of the new thread:
The first and minor problem is that, while I can receive the signals from the Worker thread (namely: invokeTestResultsUpdate), I cannot invoke the init method by emitting the emitInit signal from MainWindow. It just doesn't fire unless I call it directly or connect it via Qt::DirectConnection . Why is this happening? Because I have to start the Worker thread's own messaging loop explicitly? Or some other thing I'm not aware of? (I really fail to wrap my head around the concept of Thread/Event Loop/Signal Slot mechanism and the relation between each other even though I try. I welcome any fresh perspective here too.)
The second and more obscure problem is: run1553process method does some heavy work. By heavy work, I mean a very high rate of data. There is a loop running, and I try to receive the data flowing from a device (real-time) as soon as it lands in the buffer, using mostly extern API functions. Then throw the mentioned invokeTestResultsUpdate signal towards the GUI each time it receives a message, updating the message number box. It's nothing more than that.
The thing I'm experiencing is weird; normally the messaging routine is mostly unhindered but when I resize the main window, move it, or hide/show the window, the Worker thread skips many messages. And the resizing action is really slow (not responds very fast). It's really giving me a cancer.
(Note: I have tried subclassing QThread before, it did not mitigate the problem.)
I've been reading all the "Thread Affinity" topics and tried to apply them but it still behaves like it is somehow interrupted by the GUI thread's events at some point. I can understand MainWindow's troubles since there are many messages at the queue to be executed (both the invoked slots and the GUI events). But I cannot see as to why a background thread is affected by the GUI events. I really need to have an extremely robust and unhindered message routine running seperately behind, firing and forgetting the signals and not giving a damn about anything.
I'm really desperate for any help right now, so any bit of information is useful for me. Please do not hesitate to throw ideas.
TL;DR: call QCoreApplication::processEvents(); periodiacally inside run1553process.
Full explanation:
Signals from the main thread are put in a queue and executed once the event loop in the second thread takes control. In your implementation you call run1553Process as soon as the thread starts. the control will not go back to the event loop until the end of that function or QCoreApplication::processEvents is manually invoked so signals will just sit there waiting for the event loop to pick them up.
P.S.
you are leaking both the worker and the thread in the code above
P.P.S.
Data streams from devices normally provide an asynchronous API instead of you having to poll them indefinetly
I finally found the problem.
The crucial mistake was connecting the QThread's built in start() signal to run1553Process() slot. I had thought of this as replacing run() with this method, and expected everything to be fine. But this caused the actual run() method to get blocked, therefore preventing the event loop to start.
As stated in qthread.cpp:
void QThread::run()
{
(void) exec();
}
To fix this, I didn't touch the original start() signal, instead connected another signal to my run1553Process() independently. First started the thread ordinarily, allowed the event loop to start, then fired my other signals. That did it, now my Worker can receive all the messages.
I think now I understand the relation between threads and events better.
By the way, this solution did not take care of the message skipping problem entirely, but I feel that's caused by another factor (like my message reading implementation).
Thanks everyone for the ideas. I hope the solution helps some other poor guy like me.
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 implemented a three state machine and declared a function that change the current state of the machine:
void changeState(s1);
that contains the following command in order to change machine state:
s0->addTransition(s1)
When I compile it no error appears, but when I run the application the following message appears:
QObject::setParent: Cannot set parent, new parent is in a different thread
Shall I neccesarily connect the trnasition to a signal?
Thanks a lot for your help.
Luca
With what you explained, I would tell the issue is not from the connection itself. QT doesn't accept parent/child to be located in different thread. This means your whole state machine has to run in one single thread.
In order to run it in a thread different than the main thread you need to create your QStatemachine without parent, add all state and then move it to a different thread using QObject::moveToThread.
You may also fully create your state machine from an other thread altrough I never did that. Creating element in the main is most of the time a more straight forward implementation. You may then move them as you want.
And yes, you may add transition without signals. In this case the state just has to be activate by other means, by reimplementing QAbstractTransition.
in my C++ based BlackBerry 10 app I have a custom class that uses QNetworkAccessManager to handle network connections. The requestFinished(..) method of QNetworkAccessManager object emits a signal when it receives some data.
The thing is, many outside classes are interested in this signal. So, I have many slots connected to this signal. My problem is that, in those slots, I may be doing some UI related stuff -- so I may not want that once the signal is emitted, ALL slots get called simultaneously all the time.
Rather I may want that, at one point in time, the signal calls only one slot, at another point in time, another slot, and etc. What are the ways to do this???
I thought I could do is using different QNetworkAccessManager objects (below) -- but I have heard it is not recommended??? e.g., what are other ways??? Thank you.
MyNetworkClass *network1 = new MyNetworkClass();
bool res = QObject::connect(network1, SIGNAL(signalSuccess(QVariant)), this, SLOT(CustomSLot1(QVariant)));
MyNetworkClass *network2 = new MyNetworkClass();
bool res = QObject::connect(network2, SIGNAL(signalSuccess(QVariant)), this, SLOT(CustomSLot2(QVariant)));
MyNetworkClass *network3 = new MyNetworkClass();
bool res = QObject::connect(network3, SIGNAL(signalSuccess(QVariant)), this, SLOT(CustomSLot3(QVariant)));
By default, Qt application runs only 1 thread. This means nothing can be asyncronous. When one signal is fired, the slot function is run before anything else happens.
If you want to keep UI responsive and handle 3 functions at the same time, you need to thread them. At the beginning of the slot-function, start a thread where you execute the actual functionality.
http://doc.qt.digia.com/stable/thread-basics.html
Qt also has asynchronous functions:
http://doc.qt.digia.com/stable/qtconcurrentrun.html
Basically what Gjordis is saying you have to run the custom class where the QNetworkAccessManager resides asynchronously. You have 2 simple choices :
Either invoke asynchronous the methods of your class using QtConcurrent::run
Either handle this class events in another thread, see this excellent minimal example. The only thing is that the doWork() mentionned is really a doInit() or startWork() depending on the situation.
With both of these cases it is primordial to interact with the class only using signals and slots , otherwise you may encounter races conditions. Which means the "consumer" UI thread should not use getters\setters. Locking is not a good option, as the UI thread will require to perform an eventually blocking operation to get his data.
You should emit different signals in sequence from the same Object: a signal for every different object that is interested.
In this way you can decide the order and decide if send message to all or only to some.