Qt GUI application stops realtime process when interacting with gui - c++

I have a Qt GUI application that is doing some important real time work which must not be interrupted at all costs (Forwarding some incoming Serial traffic over LAN). At the moment the application is running flawless when there is no interaction with the GUI, but as soon as you click on a button or drag the form around, it seems like the forwarding is stopped for the time the click is being processed. Forwarding is done in a QTimer loop which I already put on a different thread than the GUI thread, but no change in the outcome.
Here's some parts of the code:
class MainWindow : public QMainWindow
{
QSerialPort serialReceiver; // This is the serial object
QTcpSocket *clientConnection;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
// Some Initializations ...
QThread* timerthread = new QThread(this); // This is the thread that is supposed to do the forwarding
QTimer *timer = new QTimer(0);
timer->setInterval(25);
timer->moveToThread(timerthread);
connect(timer ,SIGNAL(timeout()),this,SLOT(readserialData())); // Run readserialData() each 25ms
timer->connect(timerthread, SIGNAL(started()), SLOT(start()));
timerthread->start();
}
void MainWindow::readserialData()
{
if(serialReceiver.isOpen() )
{
qint64 available = serialReceiver.bytesAvailable();
if(available > 0) // Read the serial if any data is available
{
QByteArray serialReceivedData = serialReceiver.readAll(); // This line would not be executed when there is an interaction with the GUI
if(isClientConnet)
{
int writedataNum = clientConnection->write(serialReceivedData);
}
}
}
}
As I said earlier, this code is running fine under idle circumstances without any data loss. Am I doing something wrong?

It is a good idea to run you important real time work in another thread. The GUI thread or main should do drawing and the other one should do processing.
Qt's documentation about GUI thread says:
GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.
And also when to use multithreading
Using Threads
There are basically two use cases for threads:
Make processing faster by making use of multicore processors.
Keep the GUI thread or other time critical threads responsive by offloading long lasting processing or blocking calls to other threads.
In your case running the realtime processing in separate thread will fix UI lagging issues and also will fix realtimeness issue.
I suggest you to read Threading basics from Qt's doc.
Threading basics

Related

Qt Gui not updated because of threading issue

I am using a third party library which takes 60-90 seconds to dynamically load several libraries. It is an unfortunate design choice, but I can't change who the built their code.
I am trying to use a QSplashScreen to at least tell the user to wait while I'm doing this one-time loading in the background. The problem is that the splash screen is not painting. I can see a window of non-painted space while the library loads. I can see the splash screen afterwards before I close it.
I looked at similar questions (e.g. Qt Splash Screen not showing) but nothing seems to resolve my problem. I have tried loading an empty QPixmap and just giving it a solid color. That doesn't show up either.
QApplication a(argc, argv);
QPixmap pxl("icon.bmp");
QSplashScreen qss(pxl);
qss.show();
qss.showMessage(QString::fromStdString("Please wait... Loading"));
a.processEvents();
MainWindow w;
//thread is blocked
w.preLoad();//this is where the lengthy process takes place
w.show();
qss.finish(&w);
I'd like to ensure that it at least paints once before I start my loading process.
------------------------EDIT-------------------------------
Let me reiterated that the call to preLoad is BLOCKING the thread. This is not an option. I have tried a separate thread for that process. I have tried with a separate thread for the splash screen as well (turning it on and then finishing whne the other thread is done). I have tried using semaphore between the two threads to accomplish this and while everything works (including the splash screen) it takes 200-800 seconds to load. That is simply not acceptable. Thus I would like to see if there is away around it from this perspective.
-------------------------Final solution--------------------------------
Thanks to the comments below I was made aware that Qt has its own threading functionality. All the problems I was seeing appear to be caused by the interplay of std::thread and Qt's own implementation.
I have a partial solution which does work. It's not as neat as it could be, but I wanted to include it in the question thread.
//in the main method code described above
MainWindow w;
w.preLoad();
while(w.IsLoading())
{
//waiting on semaphore signaling loading is complete
//this part could probably be done better with QThread
//and signals, but it is a quick fix for now
std::this_thread::sleepfor(std::chrono::milliseconds(500));
a.processEvents();
}
w.show();
qss.finish(&w);
//In the MainWindow class
void MainWindow::preLoad()
{
loading=true;//semaphore to stall main thread
QFuture<void> future = QtConcurrent::run(this, &MainWindow::LongMethod);
}
void MainWindow::LongMethod()
{
thirdPartyLibrary.impossibleCall();
loading=false;//this handles my semaphore
}
Every GUI is executed in an infinite loop, so Qt also uses it, but the blocking tasks generate that the loop is not executed correctly, showing inadequate behaviors like the one you observe.
If one wants to execute blocking tasks it is advisable to execute it in another thread for it Qt provides several possibilities:
QThread
QThreadPool and QRunnable
QtConcurrent
I recommend the following link for you to choose the right option for your case.
If you want to update the GUI view with the information generated in another thread it is advisable to use signals and slots, or use QtConcurrent.
GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread. All widgets and
several related classes, for example QPixmap, don't work in secondary
threads. A secondary thread is commonly referred to as a "worker
thread" because it is used to offload processing work from the main
thread.
Another way is to force the GUI to update for this we can use qApp->processEvents().
References:
http://doc.qt.io/qt-5/thread-basics.html
http://doc.qt.io/qt-5/threads-technologies.html

Is it possible to play loading animation indicator while processing event in QT GUI application?

Below is my code, I have resolved to my Question .Al last i got solution with help of stack overflow team .It is possible to play animation (.gif file) on main thread if you are doing long task in worker thread.And other things is as with official doc QPixmap is does not supporting in worker thread .So i hope guys it will be help for Qt developer.
int worker::do_Work()
{
int i =0;
while (i<1000000)
{
qDebug()<<":count *i=========>"<<i;
i++;
}
qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
emit finished();
}
int mywidget::popup()
{
ui->label_2->setStyleSheet("background-color:rgb(85,255,127);border-radius:10px");
ui->label_2->setWindowFlags(Qt::FramelessWindowHint);
ui->label_2->setText("Please Wait..");
ui->label_2->setAutoFillBackground(true);
QMovie *movie = new QMovie(":images/loader.gif");
ui->label_2->setMovie(movie);
ui->label_2->show();
qDebug()<<"labele show";
movie->start();
myWorker = new worker;
WorkerThread = new QThread;
myWorker->moveToThread(WorkerThread);
connect(WorkerThread, SIGNAL(started()), myWorker, SLOT(do_Work()));
WorkerThread->start();
connect(myWorker, SIGNAL(finished()), ui->label_2, SLOT(close()));
return 0;
}
If the main loop is busy because it is processing events, it will not update the GUI (because the GUI is managed by the main thread).
When you have long processing tasks, execute them in a different thread (or accept to freeze your GUI).
As I said, the GUI is and must be managed in the main thread :
GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread. All widgets and
several related classes, for example QPixmap, don't work in secondary
threads. A secondary thread is commonly referred to as a "worker
thread" because it is used to offload processing work from the main
thread.

How do I start polling with mutex locked thread in QT?

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.

Multithreading advice

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.

QTimer not firing in a thread

I have an Qt5 c++ app with 2 threads, thread A is started when the main program starts up. The start method of thread A runs successfully.
So far so good. Next, in the main program I send a signal to Thread A to start a QTimer, which it does - but that timer never expires!
Thread B handles tcp connections. When I initiate a telnet connection to my app, thread B fires up and suddenly I see my Qtimer from thread A expiring at normal intervals.
Why is the QTimer from thread A not expiring until thread B starts?
I suspect my threads are getting messed up. note the last section of code below products this:
thread of this: QThread(0x200fe00)
thread of timer: QThread(0x1fff470)
Which suggest my worker object (this), is in a different thread from my timer object. This timer thread address is actually the MAIN thread. Why? I'm confused.
Suggestions?
In my main app I create and start my thread like this:
QThread * MyControllerThread = new QThread(this);
if (MyControllerThread) {
TheController *worker = new TheController(MyControllerThread);
if (worker) {
connect(MyControllerThread, SIGNAL(started()), worker, SLOT(start()));
connect(MyControllerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(MyControllerThread, SIGNAL(finished()), MyControllerThread, SLOT(deleteLater()));
worker->moveToThread(MyControllerThread);
MyControllerThread->start();
}
and in my main app I emit a signal to the new thread:
emit sig_startlocalpeer(Types::EActionLocalServiceStart); // Move the local peer to standby mode to start remote tests
which runs a slot in my thread (TheController object):
connect(&m_remotetestintervaltimer,SIGNAL(timeout()),this,SLOT(expiredRemoteTestIntervalTimer()));
m_remotetestintervaltimer.setTimerType(Qt::VeryCoarseTimer);
m_remotetestintervaltimer.start(REMOTETEST_TIMER_INTERVAL); // Wait between ticks
qDebug() << "thread of this: " << this->thread();
qDebug() << "thread of timer: " << m_remotetestintervaltimer.thread();
Well, it's not a Qt5 bug, it's more an inaccurate understanding of Qt's thread spirit.
In Qt, you have two ways to implement a thread which are using or not an even loop. Here is just a small visual example.
No event loop
myMethodCalledInANewThread
{
do{ ... }while(...);
}
With an event loop
myMethodCalledInANewThread
{
[...]
exec();
}
(Of course you can mix a do/while with an even loop but stay simple).
In QTimer's doc, you can read:
In multithreaded applications, you can use QTimer in any thread that
has an event loop. [...] Qt uses the timer's thread affinity to
determine which thread will emit the timeout() signal. Because of
this, you must start and stop the timer in its thread; it is not
possible to start a timer from another thread.
So I'm pretty sure you don't have a second event loop in your second thread and that's why you have the behaviour you described.
To give you some tips to be totally clear with thread using Qt, I suggest you to read:
QThread doc: https://doc.qt.io/qt-5/qthread.html
QTimer doc: https://doc.qt.io/qt-5/qtimer.html
and a very good article about how QThread implementation is misunderstood by a lot of users:
You're doing it wrong: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
I hope it will help ;)
The best answer seems to be a combination of RobbieE and Kuba:
You have to explicitly set the parent of the member variable in constructor. The parent-child feature is a Qt thing that exists among classes derived from QObject, it is not a feature of C++.
I never knew this - I assumed that when an object was created, its members variables automatically had their parent set to the object. Good to know!!