gpt4 book ai didi

c++ - 信号和槽的混淆行为取决于连接类型

转载 作者:行者123 更新时间:2023-11-30 03:19:08 25 4
gpt4 key购买 nike

我有以下片段

#include <QObject>
#include <QtConcurrent>

class Foo : public QObject {
Q_OBJECT
public:
explicit Foo(QObject *parent = nullptr) : QObject(parent) {
connect(this, &Foo::signal, this, &Foo::slot, ConnectionType);
}

void startBlockingMap() {
qDebug("startBlockingMap");
slot_counter = 0;
std::atomic_int signal_counter = 0;
QtConcurrent::blockingMap(nums, [&](auto &&num) {
++signal_counter;
emit signal();
});
qDebug("result: %d signals, %d slots", int(signal_counter), int(slot_counter));
slot_counter = 0;
}

public slots:
void slot() { ++slot_counter; }

signals:
void signal();

private:
std::atomic_int slot_counter = 0;
std::vector<int> nums{1, 2, 5, 8};
};

#include "main.moc"

int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
Foo *foo = new Foo(&app);
QTimer::singleShot(10, foo, [foo, &app]() {
foo->startBlockingMap();
app.quit();
});
return app.exec();
}

它根据传递给 connect 的连接类型产生不同的结果。

ConnectionTypeQt::DirectConnection时输出为

startBlockingMap
result: 4 signals, 4 slots

这很清楚。

ConnectionTypeQt::QueuedConnection时输出为

startBlockingMap
result: 4 signals, 0 slots

这不是。我想,插槽将在 startBlockingMap 完成后执行,但它们根本没有执行。为什么?发生了什么事?

最后,ConnectionTypeQt::AutoConnection 时的结果令人惊讶。我预计它们与 Qt::DirectConnectionQt::QueuedConnection ( as documentation states ) 相同,但它们不同:

startBlockingMap
result: 4 signals, x slots

其中 x 从 0 到 4 不等,具体取决于……某事。显然,存在一些数据竞争(?)。我不知道。

为什么插槽不使用 Qt::QueuedConnection 执行?为什么连接类型为 Qt::AutoConnection 时的输出与连接类型为直接 时排队时的输出不同?为什么这么随意?

编辑:在this answer的帮助下,我看到要在 blockingMap 之后立即执行通过排队连接连接的插槽,应该通过调用 qApp->processEvents() 显式继续事件循环。

最佳答案

Which is not. I thought, slots would be executed after maps are finished, but they are not executed at all. Why? What happened?

当控件返回到事件循环时,槽会被执行,但这里是 startBlockingMap函数从事件循环中调用,所以槽在 startBlockingMap 时执行函数返回,控制返回事件循环。

Why output when connection type is Qt::AutoConnection differs from output when connection type is direct and when it is queued? Why is it so random?

blockingMap 函数使用不同的线程来调用您的 lambda,有时是来自线程池的线程,有时是执行 blockingMap 函数的线程(此处为“主”线程)。您可以通过添加行来检查 qDebug() << this->thread() << ' ' << QThread::currentThread();进入 lambda 。现在 emit slot()有时从不是对象所有者的函数中执行,因此信号排队,有时从作为对象所有者的“主”线程中执行,因此槽直接执行,您可以看到增加控制台。

关于c++ - 信号和槽的混淆行为取决于连接类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53978961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com