c++ - 如何监控 Qt Signal 事件队列深度

标签 c++ multithreading qt qt5

我的程序中有两个对象。一个物体正在发出信号。另一个在槽中接收信号,并一个接一个地处理传入的信号。这两个对象都在不同的线程中运行。现在我需要测量和监控接收对象的工作量。

问题是我不知道在 Qt 信号队列中有多少信号在等待我的第二个对象处理。有没有办法获得这个队列的大小?或者是否有解决方法来了解仍有多少信号需要处理?

最佳答案

qGlobalPostedEventsCount()是一个起点,尽管它只适用于当前线程。

要轮询任意线程,我们可以使用 Qt 的内部机制。那么实现就非常简单了。即使线程被阻塞并且不处理事件,它也能正常工作。

// https://github.com/KubaO/stackoverflown/tree/master/questions/queue-poll-44440584
#include <QtCore>
#include <private/qthread_p.h>
#include <climits>

uint postedEventsCountForThread(QThread * thread) {
   if (!thread)
      return -1;
   auto threadData = QThreadData::get2(thread);
   QMutexLocker lock(&threadData->postEventList.mutex);
   return threadData->postEventList.size() - threadData->postEventList.startOffset;
}

uint postedEventsCountFor(QObject * target) {
   return postedEventsCountForThread(target->thread());
}

如果真的不想使用私有(private) API,我们可以采用一种不那么直接但开销更大的解决方案。首先,让我们回想一下“在某个对象的线程中做事”的最低开销方式是在事件的析构函数中做所说的“事” - 参见this answer for more details .我们可以将最高优先级的事件发布到目标对象的事件队列中。该事件包装了一个调用 qGlobalPostedEventsCount 的任务,更新计数变量,并释放我们随后获取的互斥量。在获取互斥量时,计数具有返回的有效值。如果目标线程无响应且请求超时,则返回-1

uint qGlobalPostedEventsCount(); // exported in Qt but not declared
uint postedEventsCountForPublic(QObject * target, int timeout = 1000) {
   uint count = -1;
   QMutex mutex;
   struct Event : QEvent {
      QMutex & mutex;
      QMutexLocker lock;
      uint & count;
      Event(QMutex & mutex, uint & count) :
         QEvent(QEvent::None), mutex(mutex), lock(&mutex), count(count) {}
      ~Event() {
         count = qGlobalPostedEventsCount();
      }
   };
   QCoreApplication::postEvent(target, new Event(mutex, count), INT_MAX);
   if (mutex.tryLock(timeout)) {
      mutex.unlock();
      return count;
   }
   return -1;
}

还有一个测试工具:

int main(int argc, char ** argv) {
   QCoreApplication app(argc, argv);
   struct Receiver : QObject {
      bool event(QEvent *event) override {
         if (event->type() == QEvent::User)
            QThread::currentThread()->quit();
         return QObject::event(event);
      }
   } obj;
   struct Thread : QThread {
      QMutex mutex;
      Thread() { mutex.lock(); }
      void run() override {
         QMutexLocker lock(&mutex);
         QThread::run();
      }
   } thread;
   thread.start();
   obj.moveToThread(&thread);
   QCoreApplication::postEvent(&obj, new QEvent(QEvent::None));
   QCoreApplication::postEvent(&obj, new QEvent(QEvent::None));
   QCoreApplication::postEvent(&obj, new QEvent(QEvent::None));
   QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
   auto count1 = postedEventsCountFor(&obj);
   thread.mutex.unlock();
   auto count2 = postedEventsCountForPublic(&obj);
   thread.wait();
   auto count3 = postedEventsCountFor(&obj);
   Q_ASSERT(count1 == 4);
   Q_ASSERT(count2 == 4);
   Q_ASSERT(count3 == 0);
}
QT = core-private
CONFIG += console c++11
CONFIG -= app_bundle
TARGET = queue-poll-44440584
TEMPLATE = app
SOURCES += main.cpp

关于c++ - 如何监控 Qt Signal 事件队列深度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44440584/

相关文章:

c++ - 在神秘的情况下,QCoreApplication 的用户参数为空

c++ - 从控制台 C++ 抓取打印语句

c++ - osx 构建配置上的 .framework 文件

c++ - 如何帮助编译器推导模板参数?

c++ - QFutureWatcher 如何观察多个任务/ future 和 finished() 信号

c - 它是如何工作的? pthread_cond_signal() 和 pthread_cond_wait()

c++ - 删除两个 vector 中的重复项

c# - 多核文本文件解析

c++ - 将单例类转换为一种上下文

c++ - 更改 QT 应用程序的 TARGET 编译名称