我有一个问题,我正在寻找创建一个处理类,我想将数据提供给它,然后将其放入一个线程,并告诉它开始工作。目前,我必须这样做:
ProcessingClass *worker = new ProcessingClass(myData);
connect(this, SIGNAL(startWorking()), worker, SLOT(startWorking()));
connect(worker, SIGNAL(doneWorking(data)), this, SLOT(workerFinished(data)));
QThread *workerThread = new QThread;
worker->moveToThread(workerThread);
workerThread->start();
emit(startWorking());
最终做的是创建工作者,为其提供我希望它处理的数据,连接需要连接的内容以使一切工作,将其移动到其线程,然后发出信号到开工。这或多或少做了我想要的,但有一个问题。也就是说,我想把它放到一个循环中:
while (reason){
...//gathering data to give to the worker
ProcessingClass *worker = new ProcessingClass(myData);
connect(this, SIGNAL(startWorking()), worker, SLOT(startWorking()));
connect(worker, SIGNAL(doneWorking(data)), this, SLOT(workerFinished(data)));
QThread *workerThread = new QThread;
worker->moveToThread(workerThread);
workerThread->start();
}
emit(startWorking());
这确实完成了我想要它做的事情,但它通过将所有东西都放在内存中,等到它全部存在,然后同时引发每个单独的线程来竞争资源,直到它们全部完成为止。考虑到对于我当前的数据量,这是超过1000个不同的线程,每个线程(从该程序的先前迭代)到处理信息需要1-2分钟,并且最后一个版本崩溃,因为它耗尽了内存(我认为...)我不再特别喜欢这种方法了。
我想要做的是找出一种方法将我想要的资源移动到线程,然后设置线程立即完成工作。然后我希望能够在一些线程运行后暂停循环(以便不再使计算机过载),然后继续此循环并在完成前一个线程之后启动下一个线程。
有没有更好的方法来实现这个目标?
答案 0 :(得分:1)
你应该拥有固定数量的工作线程,并且只有当线程不忙时才迭代循环。
如果您坚持使用QObject
,则可以创建一个QRunnable
包装器来运行工作对象,直到在线程池中完成,并跟踪它们的进度以发出更多工作:
class ProcessingRunnable : public ProcessingClass, public QRunnable {
void run() Q_DECL_OVERRIDE {
QEventLoop loop;
moveToThread(QThread::currentThread());
QMetaObject::invokeMethod(this, "startWorking", Qt::QueuedConnection);
loop.exec();
moveToThread(0);
}
public:
explicit ProcessingRunnable(const Data & data) :
ProcessingClass(data) {
setAutoDelete(false);
moveToThread(0); // we will be moved to a worker thread later
}
};
class JobManager : public QObject {
Q_OBJECT
QThreadPool m_pool;
QScopedPointer<ProcessingRunnable> m_worker;
int m_jobs;
public:
Q_SIGNAL void allJobsFinished();
Q_SLOT void runJobs() {
while (true) {
if (m_worker) {
if (m_pool.tryStart(m_worker.data())
m_worker.take();
else
break;
}
}
if (! reason) break;
... // gather data to give to the worker
m_worker.reset(new ProcessingRunnable(myData));
++ m_jobs;
connect(m_worker, &ProcessingRunnable::doneWorking, [this]{
-- m_jobs;
runJobs();
if (! m_jobs) emit allJobsFinished();
});
}
}
explicit JobManager(QObject * parent = 0) : QObject(parent),
m_jobs(0) {
}
}
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
...
JobManager manager;
QObject::connect(&manager, &JobManger::allJobsFinished,
&app, &QCoreApplication::quit, Qt::QueuedConnection);
manager.runJobs();
...
return app.exec();
}
对于这种类型的应用程序,让ProcessingClass
成为一个简单的仿函数而不是QObject
并使用QtConcurrent::Run
和QFutureWatcher
可能会更简单。< / p>