I have an entertaining problem to solve. I use Qt 5 for one of my projects for reading information on the network. I read modbus devices and stuff, but the real problem comes when the network isn't available.
The interface freezes and I can't interact with it. The network stuff is done in a separate thread or that is what I think. Here is some code example:
class TwidoDevice : public QObject
{
Q_OBJECT
public:
explicit TwidoDevice
........ And some useful code
The use of the (main interface) class in Window.cpp is:
L1Thread = new QThread();
L1Thread->start();
L1TWD = new TwidoDevice(L1TWD_settings,
L1TWD_Name,
PercentRegisters,
TotalsRegisters,
db, 1);
L1TWD->moveToThread(L1Thread);
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()), Qt::DirectConnection);
In this code startFired() start reading the devices on the network.
In some other function in Window.cpp:
emit startReading()
When this code is executed the interface freezes even though I've moved the L1TWD object to QThread.
When I try to debug it using the built-in debugger in QtCreator, I can't seem to understand whether the object has been moved or not and why the interface is frozen during the network call.
Has any one encountered the same problem and what is the way to solve this?
Thank you for spending time reading my question!
This is the main problem:
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()), Qt::DirectConnection);
You are connecting the receiver and sender in different threads with direct connection, which will block the UI. Given that your slot execution gets stuck, this is expected. You have at least two issues here to solve.
Use the default connection which will not block across threads, just inside the same thread. So, you would be writing something like this:
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()));
Secondly, you could make sure that your thread does not get stuck when there is some "network" problem.
For debugging purposes, please print out the current thread when having this kind of threading issues using the following methods:
[static] QThread * QThread::​currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
and this:
[static] Qt::HANDLE QThread::​currentThreadId()
Returns the thread handle of the currently executing thread.
Warning: The handle returned by this function is used for internal purposes and should not be used in any application code.
Warning: On Windows, the returned value is a pseudo-handle for the current thread. It can't be used for numerical comparison. i.e., this function returns the DWORD (Windows-Thread ID) returned by the Win32 function getCurrentThreadId(), not the HANDLE (Windows-Thread HANDLE) returned by the Win32 function getCurrentThread().
You are using a Qt::DirectConnection for your connection, which means the slot is called immediately, i.e on the same thread as the signal was fired. You can have a look at the documentation for ConnectionType. What you want to use is probably Qt::QueuedConnection, which executes the slot in the thread of the receiving object.
The best way though, as lpapp pointet out, is to let Qt decide what is best, and simply use Qt::AutoConnection, which is the default. It will use a QueuedConnection if signaling and receiving threads are different, and DirectConnection otherwise.
Related
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 am using Qt for developing a custom control interface to xmgrace, a 2D plotting library.
I have 3 components in my project:
A GUI made in Qt
A QThread which runs some shared object code from C in a background thread.
An xmgrace window connected to both the above using a pipe. (Using the grace_np library)
Communication from (1) --> (2) is done by changing status of some global variables declared in the shared object code.
Communication from (1) --> (3) & (2) --> (3) is using built in functions provided by the grace_np library.
Now, communication from (2) --> (1) is what is causing problems. I tried 2 possible ways I could think of:
a) Declaring a shared object in Qt code which emits a Qt Signal and is called within the C code.
b) Returning from the thread and using the return value to perform some operation and then restart the thread.
Both these methodologies have given unreliable results. My GUI gets stuck/causes segmentation fault and I get the message:
QProcess: Destroyed while process is still running
I am not using the QProcess class anywhere in my code. So this has become a mystery.
Please provide some info on what could be the possible causes for this.
PS: The pipe to (3) is one way and is required that way only.
Edit 1:
FYI I'm using Qt 4.2, So I can't use the QObject approach and then use a movetothread()
I'm sorry for not putting the code, as I can't due to company policies and also because I don't know what to put (Its too huge). The shared c code is 400k+ lines
I believe I have found the culprit to my problem. It seems that using the class QMessageBox is causing this problem. I was initially using static function of QMessageBox. Now I have tried declaring it over both the stack and the heap, but the problem still persists.
But I have found that removing all calls to QMessageBox from my code solves the problem.
But then the problem now is, how do I show messages?
I am just speculating here, but is it possible that the modal nature of QMessageBox is blocking the pipe existing between my program and xmgrace and subsequently causing it to quit? Then creating a custom QMessageBox (non modal) might solve this issue.
Edit 2:
I'm not calling the QMessageBox from the worker thread. Plus the way I'm using the worker thread, it never returns unless I close the program. To give an idea my QThread::run function is of the form:
QThread_Object::run()
{
c_init();
c_main();
}
where c_init & c_run are functions linked from shared c code. So it is impossible to call a QMessageBox from within these directly.
For now I'm planning on doing away with the QMessageBox and using the QMainWindow status bar instead. But then it doesn't give the entire functionality. I suppose this could be a bug in Qt 4.2
Edit 3:
I mentioned earlier that communication from (2) --> (1) was what was causing problems. Now I have done away with this communication completely and have discovered more precisely that the problem is caused by invoking QMessageBox anytime after starting the worker thread. Earlier the communication mentioned above was causing Qt to emit a signal indirectly and invoke a QMessageBox which I believe was the culprit.
Edit 4:
Ok, I forgot to mention the biggest mystery surrounding this problem since the beginning. I basically work(Place A) via ssh on a workstation(Place B) on which I code and run this program.
B is connected on 2 physical networks. A is connected to B through Network 1. Now this problem has never occured while working from my terminal at A (ie on ssh via Network 1). But it consistently occurs when I access B directly or through ssh over Network 2. Please note that every time the code is executed on B only. Both these networks are used by hundereds.
Edit 5
Finally, I have solved my problem by sub-classing QDialog and making a custom MessageBox as I don't really require the extended functionality of QMessageBox. I still don't know what precisely within QMessageBox was causing the problem. I suppose some bug within Qt which will always remain a mystery.
Since there's no code I'm shooting in the dark a little here, but it sounds like your QProcess was created on the stack, intentionally or not, or your QThread is getting destroyed prematurely. I'd put money on your QThread objects being launched incorrectly. It's hard to blame you since the documentation is (or was until recently) screwy. Consider reading this thread and this thread and don't sub-class QThread at all.
Edit:
If QMessageBox is your culprit, then I'm guessing that you're displaying it from the child thread. From the documentation:
In GUI applications, the main thread is also called the GUI thread
because it's the only thread that is allowed to perform GUI-related
operations.
There are several ways to display messages from a child thread. Personally, I use qt's error reporting scheme and redirect qCritical, qDebug, etc to stderr. Another easier way to do it would be for you to emit a QString signal from your worker thread that's caught by your GUI thread, which then displays/collects the error. I like to have my MainWindow collect the errors and then display them all at once when the worker thread finishes.
Edit 2:
Since the problem seems to be QMessageBox being modal (i.e., blocking your main thread while the worker thread moves forward), you can easily solve this by using QMessageBox in its non-modal modes. Simply pass 0 as the parent widget in the QMessageBox constructor/static function. Processing will continue without waiting for the user to exit the window--this might also result in multiple message boxes being open at the same time. If that helps you avoid the error, go over your code carefully to make sure the windows are properly destroyed after closing.
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.
The title is very cryptic, so here goes!
I am writing a client that behaves in a very synchronous manner. Due to the design of the protocol and the server, everything has to happen sequentially (send request, wait for reply, service reply etc.), so I am using blocking sockets. Here is where Qt comes in.
In my application I have a GUI thread, a command processing thread and a scripting engine thread. I create the QTcpSocket in the command processing thread, as part of my Client class. The Client class has various methods that boil down to writing to the socket, reading back a specific number of bytes, and returning a result.
The problem comes when I try to directly call Client methods from the scripting engine thread. The Qt sockets randomly time out and when using a debug build of Qt, I get these warnings:
QSocketNotifier: socket notifiers cannot be enabled from another thread
QSocketNotifier: socket notifiers cannot be disabled from another thread
Anytime I call these methods from the command processing thread (where Client was created), I do not get these problems.
To simply phrase the situation:
Calling blocking functions of QAbstractSocket, like waitForReadyRead(), from a thread other than the one where the socket was created (dynamically allocated), causes random behaviour and debug asserts/warnings.
Anyone else experienced this? Ways around it?
Thanks in advance.
I'm assuming that you're using QThread for the threading operations. If so, you can either a) use queued signal-slot connections; or b) explicitly use the QThread's event loop by creating a custom event type, posting that event in your scripting engine, and then having the client class handle those events.
example for a)
class ClientThread : public QThread
{
..stuff..
public slots:
waitForReadyRead();
};
class ScriptEngineThread : public QThread
{
..other stuff..
signals:
void requestWaitForReadyRead();
};
// In the ScriptEngineThread implementation...
ScriptEngineThread::setupClient()
{
connect(this, SIGNAL(requestWaitForReadyRead()),
client_, SLOT(waitForReadyRead()),
Qt::QueuedConnection);
}
Then, whenever you want to do the socket operations, just emit ScriptEngineThread::requestWaitForReadyRead();. The major difficulty is, I assume, you need the scripting thread to wait for some socket operation to be done. In this case you'll need to fire signals back and forth between the threads, causing some circular dependancy.
For alternative b, it would require a little more coding work, but you could:
Create your own subclasses of QEvent
Create a class to operate as a middleman, posting and handling each of your QEvents and emitting signals to communicate with the threads - each thread can have an instance of this
Connect the client and script engine to the event signals it cares about.