To connect signals/slots on separate threads using QtConcurrent
, you can use the QtConcurrent::run
function to run a slot in a separate thread, and then use a QFutureWatcher
to monitor the progress of that thread.
In your case, since the signal FileProgressChanged(Progress)
is emitted on a separate thread, you need to connect it to the OnFileProgressChanged(Progress)
slot using the QtMetaObject::Connection
class. Here's an example:
void ProgressDialog::onDriveFileProgressChanged(Progress p) {
// ...
}
QMetaObject::Connection connection = QObject::connect(drive, &Drive::fileProgressChanged, this, &ProgressDialog::onDriveFileProgressChanged);
Make sure to disconnect the signal-slot connection when you're done:
void ProgressDialog::disconnectFileProgressChanged() {
QObject::disconnect(connection);
}
Monitoring Progress Values
To monitor progress values using QFuture
and QFutureWatcher
, you can set a QFutureWatcher
as the watcher for your QFuture
. Here's an example:
void MyClass::doImportantWork(QStringList someNames) {
QFuture<void> future = QtConcurrent::map(m_initializersVector, longInitializer);
m_futureWatcher.setFuture(future);
connect(&m_futureWatcher, &QFutureWatcher<void>::resultReadyAt, this, &MyClass::initUsingFutureSlot);
connect(&m_futureWatcher, &QFutureWatcher<void>::finished, this, &MyClass::initUsingFutureSlot);
}
In your initUsingFutureSlot
slot, you can retrieve the result of the future and perform any necessary actions:
void MyClass::initUsingFutureSlot(int index) {
Initializers initializer = m_initializersVector.at(index);
BigObject *newBigObject = initializer.newBigObject;
// ...
}
Retrieving Results
To retrieve results from a QFuture
with a non-void return type, you can use the result()
method:
int result = future.result().value();
Make sure to handle any errors that may occur when retrieving the result.
ThreadPool Alternative
If you prefer to use a thread pool instead of QtConcurrent
, you can create your own thread pool using QThread
and a queue. Here's an example:
class ThreadPool {
public:
void start() {
for (int i = 0; i < m_threadCount; ++i) {
QThread *thread = new QThread();
connect(thread, &QThread::finished, this, &ThreadPool::slotThreadFinished);
m_threads.append(thread);
thread->start();
}
}
void enqueue(std::function<void()> task) {
QMetaObject::Connection connection = QObject::connect(task.get(), &QObject::destroyed, this, &ThreadPool::slotTaskDestroyed);
m_taskQueue.enqueue(task);
}
private:
int m_threadCount;
QList<QThread*> m_threads;
QQueue<std::function<void()>> m_taskQueue;
void slotThreadFinished() {
// Thread finished, start a new one
QThread *thread = new QThread();
thread->start();
}
void slotTaskDestroyed(QObject* obj) {
// Task destroyed, remove it from the queue
m_taskQueue.removeOne(obj);
}
};
You can use this thread pool to enqueue tasks and monitor their progress:
ThreadPool threadPool;
threadPool.start();
void task() {
// Perform some work...
}
threadPool.enqueue(task);
connect(&threadPool, &ThreadPool::taskFinished, this, &MyClass::slotTaskFinished);
This is just a basic example of how you can create a thread pool using QThread
. You may need to modify it to suit your specific use case.