Connecting Signals/Slots on Separate Threads

Connecting Signals/Slots on Separate Threads

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.