QProgressDialog when setValue(0) is called - c++

I have a class that is inherited from QProgressDialog. It sometimes crashes and its inside QProgressDialog class code.
I detected that when the setValue(0); is called in its constructor, crash happens. When I commented out this function, It does not crash. Even if setValue(0) is called after constructing of object crash still occurs.
This crash occurs when signals are emitted faster. Code piece shows how the function is called:
ProgressDialog progress(nullptr);
progress.setLabelText("Loading Result Files");
QFutureWatcher<void> watcher;
QFuture<void> future = QtConcurrent::run(myClassPtr,&myClass::myFunc);
QEventLoop loop;
QObject::connect(&watcher, SIGNAL(started()), &progress, SLOT(show()));
QObject::connect(&watcher, SIGNAL(finished()), &progress, SLOT(hide()));
QObject::connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
QObject::connect(transientAnimation, SIGNAL(progress(int)), &progress, SLOT(setValue(int)));
watcher.setFuture(future);
loop.exec();
progress signal is emitted inside myFunc() in another thread. In this function, multiple files are read in a folder and progress signal is emitted.
Why does this crash occur?
Thanks in advance.

Related

QFutureWatcher signal not working

My function, finishedCopy(), isn't being called when the QtConcurrent::run function copyFolder is finished. The copyFolder function does complete w/o errors.
QFutureWatcher<void> watcher;
connect(&watcher, SIGNAL(finished()), this, SLOT(MainWindow::finishedCopy()));
QFuture <void> future = QtConcurrent::run(this,&MainWindow::copyFolder,filepath,dir);
watcher.setFuture(future);
void MainWindow::finishedCopy()
{
QMessageBox::information(this,"","Done");
}
You need your watcher to live longer.. you are declaring your watcher in the stack, and so it it will get destroyed before the connection signal is emitted.
Try to declare QFutureWatcher watcher as a member variable in your MainWindow header and then connect the single to the slot in MainWindow constructor
Replace this:
connect(&watcher, SIGNAL(finished()), this, SLOT(MainWindow::finishedCopy()));
with that:
connect(&watcher, SIGNAL(finished()), this, SLOT(finishedCopy()));
Also, connect returns bool so you can always check if connection is succeded.

Wait for buttonPressed() slot to finish before executing buttonReleased()

I have a QPushButton that performs lengthy actions on pressed() and released() signals. How can I make sure that I finished executing all actions of the buttonPressed() slot, before executing the ones of the buttonReleased() slot?
I have tried with QMutex, but the program seems to be stuck in an endless loop when trying to lock upon button release, when the mutex is still locked by the buttonPressed() function:
mymainwindow.h:
#include <QMutex>
// ...
QMutex mutex;
mymainwindow.cpp:
#include <QEventLoop>
#include <QTimer>
// ...
// In the main window constructor:
connect(myButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
connect(myButton, SIGNAL(released()), this, SLOT(buttonReleased()));
// ...
void MyMainWindow::buttonPressed()
{
mutex.lock();
// Here, I do the lengthy stuff, which is simulated by a loop
// that waits some time.
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
mutex.unlock();
}
void MyMainWindow::buttonReleased()
{
mutex.lock();
// ... (some stuff)
mutex.unlock();
}
Generally using mutex is a thread sync mechanism, here you do not need thread sync since you are in the same thread. Otherwise I would suggest using QWaitCondition to wait for a flag/mutex to change (i.e. to signal your condition is now ok to go).
In your case you can just emit a signal once your "buttonPressed" actions are completed (i.e. when your timer ends?). If the end of buttonPressed() function is the when you want to execute your buttonRelease() function then you can just simply use Qt::QueuedConnection's to ensure the correct order of events (I generally don't like direct connections since they act like function calls (or even interrupts - like what I think is happening to you). So the following change might fix this for you in a simple way:
// In the main window constructor:
connect(myButton, SIGNAL(pressed()), this, SLOT(buttonPressed()), Qt::QueuedConnection);
connect(myButton, SIGNAL(released()), this, SLOT(buttonReleased()), Qt::QueuedConnection);
I am not sure if executing your event loop to "simulate" your "long amount of time" will work.... but if you do somthing more like the following to simulate your long execution time:
QElapsedTimer elapsedTime;
elapsedTime.start();
while (elapsedTime.elapsed() < 1000) // millisecs
{
// wait....
}
If this does not work, then just emit a signal at the end of buttonPressed() and set a flag in buttonReleased() such that:
void MyMainWindow::buttonPressed()
{
// actions here
emit buttonPressedDone();
}
void MyMainWindow::buttonReleased()
{
btnReleased = true;
}
void MyMainWindow::buttonPressedCompleted()
{
if (btnReleased )
{
// Do button released actions here
btnReleased = false;
}
// I am assuming that if the flag is not set then you don't want to do anything... but up to you...
}
and connect buttonPressedDone --> buttonPressedCompleted
There are load more options...these are just a few more options for you...
Is it necessary connect to release SLOT of your button? You can just connect to destroyed() SIGNAL of your QEventLoop and call buttonReleased() SLOT.
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
connect(&loop, &QEventLoop::destroyed, this, &MyMainWindow::buttonReleased);
loop.exec();
EDITED BY COMMENT:
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
connect(&loop, &QEventLoop::destroyed, [=] {
connect(myButton, &QPushButton::released, this, &MyMainWindow::buttonReleased);
});
loop.exec();

main thread cannot get signal form worker thread

This is part of the main.
This code create a worker and a workerthread.
The worker is moved to the workerthread.
The worker is then waiting for the signal to ask it to work.
The worker emit a signal with result when job done.
The main supposed to catch that signal and initialize a variable in the main.
main()
{.........
// This is the variable to be changed
variableToGetFromWorker = 0;
qDebug() << "Main thread: " << QThread::currentThreadId();
QThread workerThread;
worker* stupidTom = new stupidTom(number);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, &workerThread, &QObject::deleteLater);
connect(&workerThread, SIGNAL(start()), stupidTom, SLOT(doJob()));
connect(stupidTom, SIGNAL(jobDone(int)), this, SLOT(jobDone(int)));
workerThread.start();
workerThread.wait();
...........}
// This is a slot at main. Suppose to catch the signal from the worker
void main::jobDone(int result)
{
qDebug() << "Changing variable";
variableToGetFromWorker = result;
}
This is the doJob slot of the worker.
void worker::doJob()
{
qDebug() << "worker::doJob invoked.";
qDebug() << "worker Thread:" << QThread::currentThreadId();
// Doing Job here
emit jobDone(result);
}
It is the qDebug result
Main thread: 0x7ffff7fc6780
worker::doJob invoked.
worker Thread: 0x7fffdab44700
In Debug mode, I find that the program is stop at workerThread.wait()
and never go to main::jobDone(int result). What is the reason?
Little editing on the main code:
QThread workerThread;
worker* stupidTom = new stupidTom(number);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, &workerThread, &QObject::deleteLater);
connect(&workerThread, SIGNAL(started()), stupidTom, SLOT(doJob()));
connect(stupidTom, SIGNAL(jobDone(int)), this, SLOT(jobDone(int)));
connect(stupidTom, SIGNAL(jobDone(int)), &workerThread, SLOT(quit()));
workerThread.start();
workerThread.wait();
As long as signals supposed to invoke slots. That won't be working on wait() on the main thread that supposed to run the slot or specifically jobDone signal.
Make sure to understand the difference between QThread::exec() and QThread::wait() in your application. Normally in the real app your thread would be looping (running) while the thread that launched it is still looping as well. The loop is implemented in protected QThread::exec() method. We usually don't need to call exec() explicitly but we need to allow the thread to run. You can do that by making main function to use QEventLoop for looping:
int main()
{
//...
workerThread.start();
QEventLoop eventLoop;
// here you will probably want to hook-up QEventLoop::quit() slot
// to eventually quit the process
int returnCode = eventLoop.exec();
//...
return returnCode;
}
And this is also wrong:
connect(&workerThread, SIGNAL(start()), stupidTom, SLOT(doJob()));
Instead you should create your own job object and do QObject::moveToThread for it. Here is a nice article about it. So it should rather look like:
connect(&workerThread, SIGNAL(started()), stupidTom, SLOT(doJob()));
I likely understand why you attempted to run the thread that way as above. It is similar to many C++ examples. You can also do that in Qt but you also need to realize how exactly you'll be waiting on completion of workerThread. And Qt most popular way to do the interaction between threads is with signals and slots. That is why we should use QEventLoop in main. But of course there is an alternative. For lower level plain C++ you can use mutex and condition variable to accomplish the same. Or that same wait() but then there is no signals involved.
Also watch the debug output, whether or not all the connect statements really connect proper signals to slots. In case if there is no connect it prints the warning.

Wake up QThread::exec() from another thread

Consider MyThread that derives from QThread and implements it's run() routine like this
void MyThread::run() {
QThread::exec();
}
or equivalently
void MyThread::run() {
QEventLoop eventLoop(this);
eventLoop.exec();
}
In this state how does one cause the 'exec' to return by some action in another thread?
To consider the opposite case: without polling, how might one post an event from the thread back to the main thread?
Apparently signals that are emitted from a thread are handled in the same thread.
You seem to have some misunderstanding how QThreads are supposed to work. Unfortunately, you are not alone with this.
The first thing to do is to read about the correct usage in here:
How To Really, Truly Use QThreads; The Full Explanation
So, what you should write is something like this:
QThread* thread1 = new QThread;
QThread* thread2 = new QThread;
Task1* task1 = new Task1();
task1->moveToThread(thread1);
Task2* task2 = new Task2();
task2->moveToThread(thread2);
connect(task2, SIGNAL(finished()), thread1, SLOT(quit()));
connect(thread2, SIGNAL(started()), task2, SLOT(process()));
thread1->start();
thread2->start();
As you can see, I am using the quit() slot just like the aforementioned example. You will need to use then emit finished() in your task2 which tries to terminate thread1 or vice versa.
QEventLoop has a slot quit that you can call. If you put a reference to the eventloop in your mythread, you can then use that to call the slot.
Signals/slots can be used in a cross thread fashion. More information here: Signals and Slots Across Threads
QMetaObject::invokeMethod( eventloop, "quit", Qt::QueuedConnection)

Memory leak in QTcpServer attending connections in different thread

I'm developing a RPC server in Qt 4.7 on Windows 7.
In order to attend several executions at the same time every request run in a separate thread (as functions might be blocking). I inherited from QTcpServer and reimplemented the incomingConnection function, it looks like this:
void RpcServer::incomingConnection(int socketDescriptor){
QThread *thread = new QThread();
RpcServerConnection *client = new RpcServerConnection(socketDescriptor);
client->moveToThread(thread);
connect(thread, SIGNAL(started()), client, SLOT(init()));
connect(client, SIGNAL(finish()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
RpcServerConnection managed data exchange. The init method looks like this:
void RpcServerConnection::init(){
qDebug() << "ServerSocket(" << QThread::currentThreadId() << "): Init";
clientConnection = new QTcpSocket();
clientConnection->setSocketDescriptor(socketDescriptor);
connect(clientConnection, SIGNAL(readyRead()), this, SLOT(readFromSocket()));
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(deleteLater()));
connect(this, SIGNAL(finish()), this, SLOT(deleteLater()));
}
Once all data is received and response is sent, finish signal is emited.
Debugging I can see that all threads and sockets are deleted. However, process memory increases with every new connection and it is not freed when it ends...
Do I have to free anything else when inheriting from QTcpServer?
The problem may be with a race/undefined calling order. RpcServerConnection::finish() is connected both to its deleteLater() slot, and to the thread's quit() slot. If the thread's quit slot is entered first, the thread will terminate immediately from the event loop, before anything can be done about the deferred deletion.
Instead of:
connect(client, SIGNAL(finish()), thread, SLOT(quit()));
try:
connect(client, SIGNAL(destroyed()), thread, SLOT(quit()));