如何监控Qt信号事件队列深度
How to Monitor Qt Signal Event Queue Depth
我的程序中有两个对象。一个物体正在发出信号。另一个在插槽中接收信号并逐个处理传入信号。这两个对象在不同的线程中运行。现在,我需要测量和监视接收对象的工作负载。
问题是我不知道有多少信号在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());
}
如果真的不希望使用私有 API,我们可以有一个不那么简单的解决方案,开销更大。首先,让我们回想一下,"在某个对象的线程中做事"的最低开销方法是在事件的析构函数中做上述"事情" - 有关更多详细信息,请参阅此答案。我们可以将优先级最高的事件发布到目标对象的事件队列中。该事件包装了一个调用qGlobalPostedEventsCount
的任务,更新 count 变量,并释放我们随后获取的互斥锁。在互斥锁获取时,计数具有返回的有效值。如果目标线程无响应且请求超时,则返回-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
相关文章:
- Qt 信号/插槽问题
- Qt信号和插槽如果从QRunnable或其他线程调用,则不起作用
- C++Qt信号和插槽
- 使用std::move将std::unique_ptr作为qt信号参数传递
- 使用std::bind将Qt信号连接到插槽
- 如果代码中没有连接任何插槽,是否有理由发出Qt信号?
- 文档在哪里说明如果参数不是从末端删除参数,则无法从QT信号插槽连接中删除参数?
- 按钮组上的 Qt 信号未连接
- 通过排队的QT信号插槽连接发送QSHAREDPOINTERS的QVECTOR
- QT信号和插槽无法提供错误消息
- 如何监控Qt信号事件队列深度
- QT信号在虚拟机中不连接
- 为什么事件队列未处理我的QT信号
- 如何在打印机完成打印时从打印机获取Qt信号?
- 这是在Qt信号和插槽中使用参数调用函数的好方法吗?
- 删除 QObject 后 Qt 信号仍在触发
- Qt c++信号槽 - 清除信号所必需的
- 一个类中的QT信号/插槽,但从不同的线程发出
- QT:C 信号到QML连接
- 来自静态方法的QT信号