等待多个线程启动,start() 未捕获

Waiting for multiple threads start, started() not caught

本文关键字:start 线程 启动 等待      更新时间:2023-10-16

我正在尝试为 Qt 编写一个类似屏障的同步原语,以确保在某个点启动多个线程。但是,当我没有得到为我工作的信号(例如 started())时,我似乎遇到了这种情况。

我试图缩小代码以编译一个最小(非)工作示例。

========
main.cpp
========
#include <QtCore>
#include <QCoreApplication>
#include "qmultithreadwaiter.hpp"
#include <QSignalMapper>
#include <qdebug.h>
#define dlog qDebug()
class Test: public QThread {
public:
   virtual void run( ) {
      QThread::sleep( 500 );
   }
};
int main( int argc, char *argv[ ] ) {
   QCoreApplication a( argc, argv );
   Test t1, t2;
   QMultiThreadWaiter w;
   w.addThread(1, &t1);
   w.addThread(2, &t2);
   t1.start();
   t2.start();
   w.wait4all();
   dlog << "Wait completed";
   return 0;
}
=========================
qmultithreadwaiter.hpp
=========================    
// Qt includes
#include <QSignalMapper>
#include <QMap>
#include <QThread>
class QMultiThreadWaiter: public QThread {
Q_OBJECT
   QMap < int, bool > started;
   QSignalMapper sm;
private slots:
   void threadStarted( int id );
   void someThreadStarted();
signals:
   void allStarted( );
public:
   QMultiThreadWaiter( );
   void addThread( int id, QThread* t );
   void wait4all( );
};
=================
qmultithreadwaiter.cpp
=================
#include "qmultithreadwaiter.hpp"
// Qt includes
#include <QThread>
// Debug includes
#include <qdebug.h>
#define dlog qDebug()
// Project includes
void QMultiThreadWaiter::threadStarted( int id ) {
   dlog << "Thread #" << id << " started!";
   started[ id ] = true;
   QMapIterator < int, bool > mi( started );
   while ( mi.hasNext( ) ) {
      mi.next( );
      if ( !mi.value( ) )
         return;
   }
   dlog << "All threads started!";
   // All threads are started
   emit allStarted( );
}
void QMultiThreadWaiter::addThread( int id, QThread* t ) {
   dlog << "Adding thread " << t << " with id " << id;
   sm.setMapping( t, id );
   connect( t, SIGNAL(started()), &sm, SLOT(map()), Qt::QueuedConnection );
   connect( t, SIGNAL(started()), this, SLOT(someThreadStarted()),
            Qt::QueuedConnection );
}
void QMultiThreadWaiter::wait4all( ) {
   dlog << "Starting this thread";
   start( );
   dlog << "Going to wait";
   wait( );
   dlog << "Wait finished";
}
QMultiThreadWaiter::QMultiThreadWaiter( ) {
   sm.moveToThread( this );
   connect( &sm, SIGNAL(mapped(int)), this, SLOT(threadStarted(int)),
            Qt::QueuedConnection );
   connect( this, SIGNAL(allStarted()), this, SLOT(quit()),
            Qt::QueuedConnection );
   connect( this, SIGNAL(started()), this, SLOT( someThreadStarted()),
            Qt::QueuedConnection );
}
void QMultiThreadWaiter::someThreadStarted( ) {
   dlog << "Some thread started!";
}

输出:

Adding thread  QThread(0x28fefc)  with id  1 
Adding thread  QThread(0x28fef4)  with id  2 
Starting this thread 
Going to wait
<stuck>

奇怪的是,即使是someThreadStarted()也没有被要求this.请指教。

您的所有线程都没有运行事件循环。当你从main()调用w.wait4all();时,当执行达到wait()时,主线程会阻塞。使用 Qt::QueuedConnection 连接信号意味着当目标线程上的控件返回到事件循环时,将调用您的插槽,这永远不会用于您的测试线程。同时,你的主线程在wait()被阻塞,并且也缺少一个事件循环(QCoreApplication::exec()永远不会被调用)。主线程也无法处理它收到的排队信号,这就是为什么this线程似乎也没有发出started()