Qt: The relation between Worker thread and GUI Events - c++

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.

Related

Can I use QTimer to replace QThread?

More precisely, the question should be:
What's the difference between connecting the signal QTimer::timeout to my working function and creating a worker thread with QThread?
I am writing a program which receives streaming data in main thread (the signal is generated by QIODevice::readread())and processes them concurrently. For now I start a QTimer constantly firing signal QTimer::timeout, and the signal is connected to a working function in main thread which does the data processing stuff. This is how I achieve the concurrency.
I wonder if this approach different from creating another thread with QThread, since the idea I've found in this topic is very simliar to what I've done. The only difference is that the accepted answer creates another thread and moves timer and worker class on it. Besides the difference, I can't see any necessity of using a thread in my case.
In my case (receiving data in main thread and processing them concurrently), am I doing OK using QTimer or should I create a QThread? I am quite new to multi-threading, and if I misunderstand something, please help correct me. Thank you.
[Edit]:
I don't know what's the difference/advantage of creating a new thread to process the data. For now, everything is doing in one thread: I keep storing data in a queue and dequeue them one by one in a function triggered by QTimer::timeout.
What's the difference between connecting the signal QTimer::timeout to my working
function and creating a worker thread with QThread?
When you connect some signal/slot pair from the objects which has the same thread affinity, then the connection is direct. What it means is in your case, the main thread creates the timer, and also contains the slot, so the signal will be emitted in the main thread and also will be processed in the main thread (as the slot is also in the main thread).
When you connect some signal/slot pair from the objects which has the different thread affinity, then the connection is queued. That means signal emission and slot execution will run in different threads.
You are not really achieving concurrency, the timer signal and processing slot are executing in main thread sequentially.
So here are your options:
If you want to process data in main thread, current code is ok.
If you want to emit timeout in main thread and process data in different thread then create new class with the processing method and use moveToThread with object of that class.
The link you provided really has a different situation. In your case (correct me if I am wrong), you process data only when data is available, not just after a specified time. Your situation is much like traditional producer/consumer problem. My proposal is to not use QTimer at all. Instead create a new class with a slotwhich will process data. Then emit a signal from main thread when data is available, and connect if to the processing slot. You will achieve real concurrency. In this case you will need to implement locking for shared data access, it is easy in Qt, you can just use QMutexLocker
First, a little background:
One of the fundamental ideas behind threads is that a thread can only do one thing at a time. It may be updating the GUI, or processing data, or communicating with a remote server, but it can't be doing all those things at once.
That's where multi-threading comes in. You probably want your computer to be doing many things at once (watching videos, browsing the web, listening to music, and writing code all at the same time). The computer allows you to do that by scheduling each of these tasks on a separate threads and switching between them in periodic intervals.
In the old days, before multi-core processors, this was achieved solely by multitasking (the processor would interrupt the currently executing thread, switch to another thread context and execute the other thread for a while before switching again). With modern processors, you can have several threads executing at the EXACT same time, one on each core. This is typically referred to as multiprocessing.
Now, back to your question:
A thread can only do one thing at a time and, if you use a timer, you are using the main (AKA GUI) thread to process your data. This thread is typically responsible for responding to OS events and updating the GUI (hence GUI thread). If you don't have a lot of data to process, it's typically OK to do so on the GUI thread. However, if the data processing time has a chance of growing, it is recommended to execute such processing on a separate thread to make sure that the UI remains responsive (and so that you don't get the annoying "Your program is not responding" message from the OS). Basically, if data processing can take longer than ~200ms, it is recommended to execute the processing on a separate thread so that the user doesn't feel like the GUI is "stuck".

QThread doesn't start

Sorry for the length of this post. But I am stuck for two days now....
I am working on a Qt 4.6 Windows application that communicates with a hardware device through ActiveX.
When I send a command, the device does some stuff and when it's done (can take up to one minute) it emits a signal. I need to wait this signal to know if everything went okay (or not) and do some actions in consequence.
A command is sent to the device when a user clicks a button. And obviously, I don't want the HMI to freeze.
I am convinced I have to use threads. So I identified three threads:
the main thread corresponding to the HMI
the hardware controller (which locks after a command is sent and waits a signal)
a hardware notification listener that continuously gets signals from the hardware and unlock the thread 2
Here is the class diagram:
And a sequence diagram to show how I see things:
Explanations:
When the user launches my application, the HMI is created. The constructor of the HMI calls the constructor of the Worker. It constructs the hardware QAxObject. Then it constructs the HardwareListener giving in reference: the QAxObject, the QMutex and the QWaitCondition. Then the constructor of the Worker moves the HardwareListener object to another thread and starts it. Finally, the constructor of the HMI starts the thread of the Worker.
Then, when the user clicks a button, the HMI sends a signal to the Worker. The Worker sends a command to the hardware (that command may block the thread several seconds that's why I need the HardwareListener in another thread not to miss a signal). Then the Worker waits for a QWaitCondition (after having locked the QMutex).
After that, the hardware device sends a signal to the HardwareListener which wakes up the QWaitCondition. Therefore, the Worker thread stops waiting and finishes its actions. Finally, the Worker informs the HMI.
Problem:
The Worker and HardwareListener threads aren't created/started. Everything is done in the main thread so, obviously, it doesn't work. I don't exchange any special object between threads (so no need for qRegisterMetaType())
Question:
Is my design acceptable? There may be some other ways to do but it seems to me this is the most straightforward (taking into account the complexity).
EDIT:
I've changed my code to remove the QThread inheritance. I use the moveToThread() method instead.
Now the threads work fine. HOWEVER I have an ActiveX error: QAxBase: Error calling IDispatch member NewProject: Unknown error.
It seems the interfacing with the hardware is broken... Any idea?
Here is something interesting:
You cannot move a QAxObject to another thread once it has been created.
SOLUTION:
Here is what I have found.
Inheriting from QThread is not good design. If the work you are doing is computational heavy I would recommend using QThreadPool. I not than its better to use an asynchronous design. This means only calling function which never block and instead connect to signals notifying you that something happened.
So for example sending the command to the hardware and emitting a signal once the hardware is done. If the hardware API doesn't supply async functions than you are stuck with using threads.
QtConcurrentRun can help with that. Usually you should not need to touch threads yourself; and its a hell of a lot easier without.

boost::asio, threads and synchronization

This is somewhat related to this question, but I think I need to know a little bit more. I've been trying to get my head around how to do this for a few days (whilst working on other parts), but the time has come for me to bite the bullet and get multi-threaded. Also, I'm after a bit more information than the question linked.
Firstly, about multi-threading. As I have been testing my code, I've not bothered with any multi-threading. It's just a console application that starts a connection to a test server and everything else is then handled. The main loop is this:
while(true)
{
Root::instance().performIO(); // calls io_service::runOne();
}
When I write my main application, I'm guessing this solution won't be acceptable (as it would have to be called in the message loop which, whilst possible, would have issues when the message queue blocks waiting for a message. You could change it so that the message-loop doesn't block, but then isn't that going to whack the CPU usage through the roof?)
The solution it seems is to throw another thread at it. Okay, fine. But then I've read that io_service::run() returns when there is no work to do. What is that? Is that when there's no data, or no connections? If at least one connection exists does it stay alive? If so, that's not so much of a problem as I only have to start up a new thread when the first connection is made and I'm happy if it all stops when there is nothing going on at all. I guess I am confused by the definition of 'no work to do'.
Then I have to worry about synchronizing my boost thread with my main GUI thread. So, I guess my questions are:
What is the best-practice way of using boost::asio in a client application with regard to threads and keeping them alive?
When writing to a socket from the main thread to the IO thread, is synchronization achieved using boost::asio::post, so that the call happens later in the io_service?
When data is received, how do people get the data back to the UI thread? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. It wasn't elegant, but it worked.
I'll be reading some more today, but it would be great to get a heads up from someone who has done this already. The Boost::asio documentation isn't great, and most of my work so far has been based on a bit of the documentation, some trial/error, some example code on the web.
1) Have a look at io_service::work. As long as an work object exists io_service::run will not return. So if you start doing your clean up, destroy the work object, cancel any outstanding operations, for example an async_read on a socket, wait for run to return and clean up your resources.
2) io_service::post will asynchronously execute the given handler from a thread running the io_service. A callback can be used to get the result of the operation executed.
3) You needs some form of messaging system to inform your GUI thread of the new data. There are several possibilities here.
As far as your remark about the documention, I thing Asio is one of the better documented boost libraries and it comes with clear examples.
boost::io_service::run() will return only when there's nothing to do, so no async operations are pending, e.g. async accept/connection, async read/write or async timer wait. so before calling io_service::run() you first have to start any async op.
i haven't got do you have console or GUI app? in any case multithreading looks like a overkill. you can use Asio in conjunction with your message loop. if it's win32 GUI you can call io_service::run_one() from you OnIdle() handler. in case of console application you can setup deadline_timer that regularly checks (every 200ms?) for user input and use it with io_service::run(). everything in single thread to greatly simplify the solution
1) What is the best-practice way of using
boost::asio in a client application
with regard to threads and keeping
them alive?
As the documentation suggests, a pool of threads invoking io_service::run is the most scalable and easiest to implement.
2) When writing to a socket from the main
thread to the IO thread, is
synchronization achieved using
boost::asio::post, so that the call
happens later in the io_service?
You will need to use a strand to protect any handlers that can be invoked by multiple threads. See this answer as it may help you, as well as this example.
3) When data is received, how do people
get the data back to the UI thread? In
the past when I used completion ports,
I made a special event that could post
the data back to the main UI thread
using a ::SendMessage. It wasn't
elegant, but it worked.
How about providing a callback in the form of a boost::function when you post an asynchronous event to the io_service? Then the event's handler can invoke the callback and update the UI with the results.
When data is received, how do people get the data back to the UI thread? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. It wasn't elegant, but it worked
::PostMessage may be more appropriate.
Unless everything runs in one thread these mechanisms must be used to safely post events to the UI thread.

what can I use to replace sleep and usleep in my Qt app?

I'm importing a portion of existing code into my Qt app and noticed a sleep function in there. I see that this type of function has no place in event programming. What should I do instead?
UPDATE: After thought and feedback I would say the answer is: call sleep outside the GUI main thread only and if you need to wait in the GUI thread use processEvents() or an event loop, this will prevent the GUI from freezing.
It isn't pretty but I found this in the Qt mailing list archives:
The sleep method of QThread is protected, but you can expose it like so:
class SleeperThread : public QThread
{
public:
static void msleep(unsigned long msecs)
{
QThread::msleep(msecs);
}
};
Then just call:
SleeperThread::msleep(1000);
from any thread.
However, a more elegant solution would be to refactor your code to use a QTimer - this might require you saving the state so you know what to do when the timer goes off.
I don't recommend sleep in a event based system but if you want to ...
You can use a waitcondition, that way you can always interrupt the sleep if neccesary.
//...
QMutex dummy;
dummy.lock();
QWaitCondition waitCondition;
waitCondition.wait(&dummy, waitTime);
//...
The reason why sleep is a bad idea in event based programming is because event based programming is effectively a form on non-preemptive multitasking. By calling sleep, you prevent any other event becoming active and therefore blocking the processing of the thread.
In a request response scenario for udp packets, send the request and immediately wait for the response. Qt has good socket APIs which will ensure that the socket does not block while waiting for the event. The event will come when it comes. In your case the QSocket::readReady signal is your friend.
If you want to schedule an event for some point of time in the future, use QTimer. This will ensure that other events are not blocked.
It is not necessary to break down the events at all. All I needed to do was to call QApplication::processEvents() where sleep() was and this prevents the GUI from freezing.
I don't know how the QTs handle the events internally, but on most systems at the lowest level the application life goes like this: the main thread code is basically a loop (the message loop), in which, at each iteration, the application calls a function that gives to it a new message; usually that function is blocking, i.e. if there are no messages the function does not return and the application is stopped.
Each time the function returns, the application has a new message to process, that usually has some recipient (the window to which is sent), a meaning (the message code, e.g. the mouse pointer has been moved) and some additional data (e.g. the mouse has been moved to coords 24, 12).
Now, the application has to process the message; the OS or the GUI toolkit usually do this under the hood, so with some black magic the message is dispatched to its recipient and the correct event handler is executed. When the event handler returns, the internal function that called the event handler returns, so does the one that called it and so on, until the control comes back to the main loop, that now will call again the magic message-retrieving function to get another message. This cycle goes on until the application terminates.
Now, I wrote all this to make you understand why sleep is bad in an event driven GUI application: if you notice, while a message is processed no other messages can be processed, since the main thread is busy running your event handler, that, after all, is just a function called by the message loop. So, if you make your event handler sleep, also the message loop will sleep, which means that the application in the meantime won't receive and process any other messages, including the ones that make your window repaint, so your application will look "hang" from the user perspective.
Long story short: don't use sleep unless you have to sleep for very short times (few hundreds milliseconds at most), otherwise the GUI will become unresponsive. You have several options to replace the sleeps: you can use a timer (QTimer), but it may require you to do a lot of bookkeeping between a timer event and the other. A popular alternative is to start a separate worker thread: it would just handle the UDP communication, and, being separate from the main thread, it would not cause any problem sleeping when necessary. Obviously you must take care to protect the data shared between the threads with mutexes and be careful to avoid race conditions and all the other kind of problems that occur with multithreading.

Crash with boost::thread

I am using wxwidgets together with boost::thread. The Thread is a worker thread which sends some Events to the GUI:
Thread creation:
thrd = boost::thread(boost::bind(workerFunction,this));
Send Message to the GUI:
wxPostEvent(loWindow, event);
wxSafeYield();
Under Windows I don't see any problems, but when starting the application under Linux (Ubuntu 8.10), it stops with the following error message:
_XCBUnlockDisplay: Assertion `xcb_get_request_sent(dpy->xcb->connection) == dpy->request' failed.
Aborted
What am I missing? When the workerFunction is not started in a thread, it works without problems.
Regards,
/mspoerr
Don't call wxYield from a worker thread. Only do that from the GUI thread. Yield will process gui events, and is intended to be used if in some GUI event handler you do much of work and want to update other controls and process pending events in between. The Safe in wxSafeYield means that it disables GUI controls before it processes pending events first. That will protect you from such cases like entering the event handler you called wxYield from a second time, recursively. It doesn't mean that it is thread-safe, or something like that.
If you want to give the rest of the time slice your thread would have to other threads, call wx's wxThread::Yield or boost's this_thread::yield (depending on your thread class) instead.
The problem was with the data I sent - for complex data you need to use custom events. I now implemented a custom event and it works.
For more information please see http://forums.wxwidgets.org/viewtopic.php?t=24663
Thank you for your help!
/mspoerr
EDIT: Updated the link. The old one was broken