在生成的线程中启动进程

时间:2015-07-13 19:43:03

标签: c++ qt

我有一个问题,我正在寻找创建一个处理类,我想将数据提供给它,然后将其放入一个线程,并告诉它开始工作。目前,我必须这样做:

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分钟,并且最后一个版本崩溃,因为它耗尽了内存(我认为...)我不再特别喜欢这种方法了。

我想要做的是找出一种方法将我想要的资源移动到线程,然后设置线程立即完成工作。然后我希望能够在一些线程运行后暂停循环(以便不再使计算机过载),然后继续此循环并在完成前一个线程之后启动下一个线程。

有没有更好的方法来实现这个目标?

1 个答案:

答案 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::RunQFutureWatcher可能会更简单。< / p>