Reputation: 679
I have a function that creates a bunch of QThreads to speed up a long calculation, but when I try and sleep until the calculation is done, the background threads never execute for some reason.
I can't figure out why the threads don't execute after I call thread->start()
. Here's my code:
multithread.run_multithread(run_function, thread_count);
while(multithread.running)
QThread::msleep(100);
qDebug() << "done"; // Never reaches this point
And the multithread function:
void Multithread::run_multithread(std::function<void
(int)>run_function_in, int thread_count) {
running = true;
// Create workers and threads
int thread_idx;
for(thread_idx=0; thread_idx<thread_count; thread_idx++) {
ThreadWorker *worker = new ThreadWorker(this, run_function_in);
QThread *thread = new QThread();
// Set workers and threads to delete when done
worker->moveToThread(thread);
connect(worker, &ThreadWorker::finished, this, &Multithread::check_progress);
connect(thread, &QThread::started, worker, &ThreadWorker::run);
connect(worker, &ThreadWorker::finished, thread, &QThread::quit);
connect(worker, &ThreadWorker::finished, worker, &ThreadWorker::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
// Start thread
thread->start();
}
}
running
gets set to false
in Multithread::check_progress
when all the threads finish their part of the calculation. When I remove QThread::msleep(100)
the calculation will execute normally, but I need some way to block until it completes.
Upvotes: 0
Views: 3536
Reputation: 3754
Rather than using QThread, I would recommend using the Qt Concurrent functionality which provides a higher level of abstraction over the thread primitives. You can use QFutureSynchronizer
to wait for several concurrent futures to finish. This object will wait for all attached futures to finish before it allows itself to be destroyed.
An example of how to start several threads and then wait for them all to finish is:
#include <QtConcurrent>
void run_multithread(...) {
// Set up a new synchronizer.
QFutureSynchronizer<void> synchronizer;
// Run n tasks in parallel.
for (int thread_idx = 0; thread_idx < thread_count; ++thread_idx) {
synchronizer.addFuture(QtConcurrent::run(run_function_in));
}
// The synchroniser will wait for all threads to finish before returning.
}
Upvotes: 1
Reputation: 6776
It could be because of optimization, since multithread.running
is not changed inside the loop. However, here the main reproducible reason is that the slot Multithread::check_progress
is never called by ThreadWorker::finished
signals, since the instance of Multithread
belongs to your current thread, but the event loop is blocked.
Instead of such sleep you can emit a signal from Multithread
object when all threads are finished. Then the computation may be continued from a slot connected to that signal.
Upvotes: 0