运行多个线程并等待所有完成

时间:2019-03-31 18:50:41

标签: multithreading qt5

我有一个Emitter类,用于模拟繁重的过程

class Emitter : public QObject
{
  Q_OBJECT
public:
  explicit Emitter(QObject* parent = nullptr);
  ~Emitter();
  int start();

signals:
  void finished(int id);

private slots:
  void heavyProcess();

private:
  static int globalId;
  int id;
  QThread t;
  void finish();
};

int Emitter::globalId = 1;

Emitter::Emitter(QObject* parent)
  : QObject{ parent }
  , id{ globalId++ }
{
  moveToThread(&t);
  t.start();
}

Emitter::~Emitter()
{
  qDebug() << "Destruct" << id;
  t.quit();
  t.wait();
}

int
Emitter::start()
{
  QMetaObject::invokeMethod(this, "heavyProcess");
  return id;
}

void
Emitter::heavyProcess()
{
  auto time{ QRandomGenerator::global()->bounded(1000u, 3000u) };
  qDebug() << "Id" << id << "Time" << time;
  QThread::msleep(time);
  finish();
}

void
Emitter::finish()
{
  qDebug() << "Finished" << id;
  emit finished(id);
}

此外,还有一个 manager 可以创建Emitter类的两个实例。我想对每个实例运行繁重的过程,当所有实例完成时,管理器发出一个finished信号。

class Manager : public QObject
{
  Q_OBJECT
public:
  explicit Manager(QObject* parent = nullptr);
  void start();

signals:
  void finished();

public slots:

private slots:
  void update(int id);

private:
  QHash<int, QSharedPointer<Emitter>> emitters;
};

Manager::Manager(QObject* parent)
  : QObject{ parent }
{}

void
Manager::start()
{
  QSharedPointer<Emitter> em1{ new Emitter{} };
  QSharedPointer<Emitter> em2{ new Emitter{} };
  connect(em1.get(), &Emitter::finished, this, &Manager::update);
  connect(em2.get(), &Emitter::finished, this, &Manager::update);

  emitters.insert(em1->start(), em1);
  emitters.insert(em2->start(), em2);
}

void
Manager::update(int id)
{
  qDebug() << "update" << id;
  emitters.remove(id);
  if (emitters.isEmpty()) {
    qDebug() << "Empty";
    emit finished();
  }
}

main函数中,我希望在QCoreApplication发出其Manager信号后退出finished

int
main(int argc, char* argv[])
{
  QCoreApplication a(argc, argv);
  Manager manager;
  QObject::connect(&manager, &Manager::finished, &a, &QCoreApplication::quit);
  manager.start();
  return a.exec();
}

有时候我有这个输出

Id 1 Time 1416
Id 2 Time 1096
Finished 2
update 2
Destruct 2

这意味着Emitter类的一个实例尚未完成,可能是因为线程在有时间完成其过程之前被“杀死”了。

我的问题

  1. 这是创建多个线程以执行具有不同数据集的同一进程的正确方法吗?
  2. 为什么在线程运行时调用finished的{​​{1}}信号?
  3. 如果我管理线程的方法不正确,您能指导我做一个更好的方法吗?

0 个答案:

没有答案