I am tying to create a worker thread that will update a QTWidget at 1 second intervals (think of it as a digital clock or a progress bar updater might be a better analogy given the application).
My application is avionics specific that computes flight tracking info over a flight path and updates a map or some other QT widget regularly during the progress of the flight at 1 sec intervals (I suppose you could think of it as a sort of progress bar - where the progress bar could be replaced by a map or table widget in my case). The thread will probably take about 10-20 seconds to compute the entire flight data - (however it will have its first results available almost immediately) - these results need to be sent at 1 second intervals to the GUI to update the position of an aircraft on a map.
There is a lot of confusion about the right and wrong way to incorporate a timer that updates a worker thread. The best source of knowledge I found was a QtCon talk entitied Multithreading with Qt - Giuseppe D’Angelo - it seems that the preferred method is to have a worker QObject that does not subclass a QThread and that has the timer running in its own event handler - but there is a lot of confusion about moving the worker thread to another thread that I don't understand very well and I am looking for some canonical advice on how to do this right. Doing so in a Lambda would be ideal as I could keep the logic and threading relatively isolated which would be ideal.
I am looking to see if someone could point me in the direction of a similar example (especially if it uses modern Lambdas). I am currently using QT 5.11.2.
My worker object (which contains the QTimer is as follows):
class SimulatedFlightWorker : public QObject
{
Q_OBJECT
public:
explicit SimulatedFlightWorker()
: mpMMRFlightData{}
{}
public slots:
// worker thread slot that computes the mpMMRFlightData
void importSimulatedFlight(
const QString& fileName,
const int aPlaybackSpeed);
void updateGUI(int secondsElapsed);
signals:
// every second during the flight we need to send a new MMR
// record to the GUI - to display on a spreadsheet or google map
void updateFlightData(const MMRTimedRecord& rMMRRecord);
// this is effectively when the worker thread is done
void flightCompleted();
private:
QTimer mTimer;
// the
std::unique_ptr<MMRFlightData> mpMMRFlightData;
};
This is the code where I setup the signals and slots (not working yet)
// Experimental worker model adapted from YouTube tutorial
// by Giuseppe di Angelo https://www.youtube.com/watch?v=BgqT6SIeRn4
auto thread = new QThread;
auto worker = new SimulatedFlightWorker;
connect(thread, &QThread::started, worker, &SimulatedFlightWorker::importSimulatedFlight);
connect(worker, &SimulatedFlightWorker::flightCompleted, thread, &QThread::quit);
connect(thread, &QThread::finished, worker, &SimulatedFlightWorker::deleteLater);
worker->moveToThread(thread);
thread->start();
It’s really simple:
Your calculations are done in a QObject-derived class
Updates are issued via a signal in that object.
Calculations are done in small chunks that take 10-20ms.
The calcualtions are triggered from a zero-duration timer – it’s not a timer, but a way of detecting event loop idle state in a thread.
The updates are triggered from a 1-second timer.
This class can be run on any thread — it will even work on the GUI thread, but will make it a bit less responsive (but not at all unresponsive).
You’d normally instantiate the class, start computations, and move it to a dedicated thread.
Related
My first naive at updating my progress bar was to include the following lines in my loop which is doing the processing, making something like this:
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
//Added these lines but they don't do anything
ui->progressBar->setValue(numberProcessed++);
ui->progressBar->repaint();
}
I thought adding the repaint() would make the execution pause while it updated the GUI, but apparently it's not that simple. After looking at the questions:
QProgressBar Error
Progress bar is not showing progress
it looks like I'm going to have to put the data processing in a different thread and then connect a signal from the data processing thread to the GUI thread to update the progressbar. I'm rather inexperienced with GUIs and threads and I was wondering if anyone could just point me in the right direction, ie what Qt classes should I be looking at using for this. I'd guess I need a QThread object but I've been looking through the QProgressBar documentation but it doesn't bring up the topic of threading.
As #rjh and #Georg have pointed out, there are essentially two different options:
Force processing of events using QApplication::processEvents(), OR
Create a thread that emits signals that can be used to update the progress bar
If you're doing any non-trivial processing, I'd recommend moving the processing to a thread.
The most important thing to know about threads is that except for the main GUI thread (which you don't start nor create), you can never update the GUI directly from within a thread.
The last parameter of QObject::connect() is a Qt::ConnectionType enum that by default takes into consideration whether threads are involved.
Thus, you should be able to create a simple subclass of QThread that does the processing:
class DataProcessingThread : public QThread
{
public:
void run();
signals:
void percentageComplete(int);
};
void MyThread::run()
{
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
emit percentageCompleted(computePercentageCompleted());
}
}
And then somewhere in your GUI code:
DataProcessingThread dataProcessor(/*data*/);
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int));
dataProcessor.start();
You need to call QApplication::processEvents() periodically inside your processing loop to let it handle UI events.
As Georg says, Qt is a single-threaded co-operative multitasking environment. You get full control of your process until you relinquish it voluntarily with processEvents() - until you do that, Qt can't update the UI elements, handle async HTTP requests, handle input, or pretty much anything else. It's up to you to make sure that stuff gets a timeslice while you're in a long processing loop.
You can create a sub-class of QThread that emits a signal progressChanged, which you connect to the QProgressBar.
connect() makes the connections auto connections per default. That means that the signal-slot-mechanism already takes care of the threading issues for you, so you don't need to worry about that.
I am using Ubuntu 12.04 with Qt version 4.8.3.
In Qt main window I manage to open my devices and this part of the code is working.
Now after I open devices I need to wait if a card is present. It means I have to use polling to get the data from card. But the polling must be infinite loop. Polling for card arrival and removal.
Example poll for card arrival every 20ms and when a card is detected I need to switch poll for card removal every 20 ms. So when a card arrival or removal is detected, my app signals Qt event such that another Qt thread can now proceed to read/write the card.
I read about QThread, mutex locked so on and I am bit confused.
I have a main window plus a worker class. In my mainwindow I code as;
// Open a reader (from my SDK)
cReader.open
//If the reader is open use;
thread = new QThread();
worker = new Worker();
worker->moveToThread(thread);
connect(worker,SIGNAL(??????),SLOT(?????);
connect(worker,SIGNAL(?????),SLOT(?????);
.........
First I must use connect for SIGNAL/SLOT and start the card arrival/removal polling. Than if any card detected I have signal to another thread to read from card or write into the card.
So I don’t know where to start or how to call signal/slot? I need help to fill the ?????? above SIGNAL/SLOT.
Edited: I also need mutex lock shared by the polling thread and the card handiling thread. This is because a card poll command will invalidate my mifare session if opened.
Any help please,
Kind Regards,
Using QMutex for protection an object, on the example of your cReader:
// class member
QMutex m_mutex;
//...
QByteArray MyClass::safeReadSomeData()
{
m_mutex.lock();
QByteArray result = cReader.read();
m_mutex.unlock();
return result;
}
See also QMutexLocker, QReadWriteLock.
Common and usual way for communication and parameters exchange between threads is using signals & slots. Example:
thread = new QThread();
worker = new Worker();
worker->moveToThread(thread);
connect( thread, SIGNAL(started()), worker, SLOT(startMyWork()) );
connect( worker, SIGNAL(sigCardDetected()), someOtherObject, SLOT(onCardDetected()) );
thread->start();
//...
Useful article from official documentation: Threads and QObjects
Also I think this answer about QThread will be useful for you: https://stackoverflow.com/a/35056527/4149835
p.s. Are you sure that you need to use two different additional threads for detecting and reading/writing?
It is not thread-safe (unless one QObject accesses data in another QObject and both belong to the same thread).
In terms of usage of mutexes the QMutexLocker is your friend and I advise you to use it instead of manually handling the locking/unlocking.
If you re-read your question you will notice that you heavily use intervals. And how do we handle intervals? Using QTimer. Here is my suggestion:
Create a QTimer along with the worker QObject
Set the interval of the timer to 20ms or whatever interval you want for it to tigger an event; a timer with interval set to 0 means that an event will be triggered by it as soon as possible
Connect the timer to the slot of the worker that does the work (check if card is removed etc.)
Connect the object's slots/signals to the signals/slots of your UI (using QMutexLocker will enable you to secure the access on the internal data of both) or another QObject (in the same or a different thread where the worker is residing)
Move both the timer and worker to a QThread and start the thread
The timer will start triggering a check for your card every X milliseconds. The worker will then receive that signal from the timer (here no mutex is required since both the timer and the worker are with the same thread-affinity). Things will change internally for the worker and then it will emit a signal to another QObject or the UI itself. At this point the mutexes come into play unless you are accessing another instance of a QObject in the same thread where your worker is.
You can add as many threads as you like by doing so. I have a UI that has 6 threads running in the background accessing both the UI and each other without any problem using timers.
EDIT:
I have started working on a small demo using QTimer, QThread and QObject. Application is incomplete/buggy but you can see how QTimer works.
I am developing an application, the main goal is to grab images from a frame grabber, do some processing and then show images on a GUI.
The frame grabber is connected to the PCIe. And I'm using the frame grabber SDK.
The image stream is pretty slow 10 to 100 images/s
I am here to have some advice about my code and how to optimize it.
First, there is my run() function from a class inherited from Qthread
I grab an image and put it on a buffer queuecv:: Mat>.
void ImageIn::run(){
_cam->allocMemory();
_cam->startAquisition();
_runningThread = true;
while(_runningThread)
{
Mat image(_cam.getSizeX(), _cam.getSizeY(), CV_16U, _cam->getImageDMA0());
_ctrl->getMutexIn()->lock(); // Lock BufferIn
_ctrl->getBufferIn()->push(image); // store Image in BufferIn
_ctrl->getMutexIn()->unlock(); // Unlock bufferIn
}
}
Images are stored in a buffer and then the processing thread do some work...
void ImageProcessing::run(){
while(_runningThread){
if (_ctrl->getMutexIn()->tryLock()){
while(!_ctrl->getBufferIn()->empty()){
_ctrl->getBufferIn()->front().convertTo(tempConvert, CV_32F);
_bufferLocalIn.push(tempConvert);
_ctrl->getBufferIn()->pop();
}
_ctrl->getMutexIn()->unlock();
}
// Do some processing and put image and a buffer for GUI
}
}
So, I have some questions:
- The thread 1 gets images thanks to a blocking function, so the CPU consumption is low, but the thread 2 run continuously and consumes a lot of CPU reassess what can I do for fixing that?
- is it the right way to code that?
So i tried that :
QThread* thread = new QThread;
ImageWriter* worker = new ImageWriter();
worker->moveToThread(thread);
QTimer* timer = new QTimer();
int msec = 100;
timer->setInterval(msec);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
QObject::connect(timer, SIGNAL(timeout()), thread, SLOT(start()));
timer->start();
is it ok ?
As Qt is an event driven framework, each thread has an event queue which receives events and sends them to various objects to receive them.
If any section of code in a thread has essentially a while(1) loop, then event propagation cannot occur and this is what you're doing in both threads with
while(_runningThread)
Starving the event processing in an infinite loop is the cause of excessive CPU consumption.
It is possible to use to get Qt to process events with a call to QApplication::processEvents within the infinite loops, but this is not ideal.
A better method would be to time-slice the processing with QTimer and allow the event propagation to occur naturally. This would require deciding how long processing could occur, before saving the processing state and then returning back to the event loop. A tick of the timer would call your processing function which can then restore state and resume.
This method will be easier if you create a processing class derived from QObject which you move to a QThread, rather than inheriting directly from QThread itself. There's a great article on How to Really Truly Use QThread which can be used as a template on how to do this.
Finally, consider that you can have more than one QThread, as well as more than one QObject running on a QThread. As a general rule, you will not benefit if the number of threads exceeds the number of processor cores available.
If you know the target machine is a quad core, you can create 3 extra QThreads (4 in total, including main), create multiple processing objects and move them to different threads to provide optimal processing.
I am writing a mathematical simulator in Qt5 and when I click a button, some heavy calculation needs to be done. During it, I want to display a Please, wait window, eventually with a progress bar. Preferably without using threads.
Problem is, during calculation the application hangs, events are not handled, and what should be a please, wait window is merely a window frame without any contents (looks transparent).
PC: AMD X2 L325, 2GB RAM, Radeon E4690
OS: Debian 6 (Squeeze, Old stable)
gcc 4.4.5, Qt 5.2.0
Any help would be appreciated!
While you could call QApplication::processEvents, it's not the best approach.
If you're avoiding threads because they're new to you, then I'm sure you'll find it much easier once you've done it once. Qt makes it easy.
All you need to do is create a class derived from QObject which will do the calculations. Next, create a thread and call the object's moveToThread function. The thread is then controlled with a few signals and slots. That's all there is to it.
Rather than repeat the content here, I suggest you read this article, which explains it in detail and provides clean and concise example code.
From the new object that processes your calculations, it can then emit a signal to a slot on the main thread, which will update the progress on your "Please Wait" window.
Note that Widgets and all rendering must be done on the main thread.
I prefer use Qt Concurrent. It is not well documented, but very handy, much better then using QThread directly.
I usually do such things like that I have separate QObject for logic, in there some slot which calls heavy calculation like that (see run documentation):
void MyCalculationClass::startCalculating() {
QtConcurent::run(this, &MyCalculationClass::doHeavyCalculation);
}
Where method doHeavyCalculation emits signals with progress and calculation results.
Usually this method operates on its own data not modified by other threads/methods, so if synchronization is needed, it is trivial. Signal-Slot mechanism is handling most of the multithreading issues (note that default connections detects that signals is emitted from other threads and queues slot calls in proper thread, it is done automatically by default).
i have such problem and i solve it like this, i make calculation in another thread( i use std::thread instad of QThread) before i start my calculation i just start timer
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(repaint()));
timer->start(1);
and then
std::thread t(&Widget::calcBackgound, this);
t.detach();
You can put the heavy and time consuming part of your code in run() member function of another class which inherits from QThread. After that create an instance of the new class and simply call its start() function.
Your new class can have a signal which emits the current progress value. you can then connect this signal to the slot of a progress bar.
I am new on Qt programming. I have to make some computations which take long time. I use an edit box and two button named as "start" and "stop". The edit box is used for the initialization. Start button starts the computation. While the computation is going on, I must be able to stop the computation whenever I want. But when I start the computation by clicking the start button. As expected, I cannot click any component on the window until the computation is completed.
I want to use the components (especially stop button) on the window normally while the computation is performing. But I am not good on the threads, I am looking for an easier method. Is there any simple solution?
There are a couple of options.
1. Subclass QRunnable
Subclass QRunnable and use QThreadPool to run it in a separate thread. To communicate with the UI, use signals. Example of this:
class LongTask: public QRunnable
{
void run()
{
// long running task
}
};
QThreadPool::globalInstance()->start(new LongTask);
Note that you don't need to worry about managing the thread or the lifetime of your QRunnable. For communicating, you can connect your custom signals before starting the QRunnable.
2. Use QtConcurrent::run
This is a different approach and might not suit your problem. Basically, the way it works is the following: you get a handle to the future return value of the long task. When you try to retrieve the return value, it will either give it to you immediately or wait for the task to finish if it hasn't already. Example:
QFuture<int> future = QtConcurrent::run(longProcessing, param1, param2);
// later, perhaps in a different function:
int result = future.result();
3. Subclass QThread
You probably don't need this, but it isn't hard either. This one is very similar to #1 but you need to manage the thread yourself. Example:
class MyThread : public QThread
{
public:
void run()
{
// long running task
}
};
QThread* thread = new MyThread(this); // this might be your UI or something in the QObject tree for easier resource management
thread.start();
Similarly to QRunnable, you can use signals to talk to the UI.
In your computation you can put QCoreApplication::processEvents(); so that GUI events also get processed. This will omit usage of threads.
You can have your computation occur in a different thread than your GUI. When the GUI recieves a signal that the stop button is pressed, you change a flag value which your computation thread periodically checks. When the flag is set, you can terminate the computation thread.
Either use threads (perhaps synchronizing them by sending messages on pipes to self), or use timer (with a 0 millisecond delays, this is how idle processing is done in Qt).