У меня есть следующий фрагмент
#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
.
Когда ConnectionType
равен Qt::DirectConnection
вывод равен
startBlockingMap
result: 4 signals, 4 slots
Что ясно.
Когда ConnectionType
равно Qt::QueuedConnection
, вывод равен
startBlockingMap
result: 4 signals, 0 slots
Что не соответствует.Я думал, что слоты будут выполнены после завершения startBlockingMap
, но они не будут выполнены вообще.Зачем?Что случилось?
Наконец, результаты, когда ConnectionType
равен Qt::AutoConnection
, являются неожиданными.Я ожидал, что они будут такими же, как для Qt::DirectConnection
или Qt::QueuedConnection
(, как указано в документации ), но они отличаются:
startBlockingMap
result: 4 signals, x slots
Где x
изменяется от 0 до 4в зависимости от ... чего-то.Видимо, есть какая-то гонка данных (?).Я не знаю.
Почему слоты не выполняются с Qt::QueuedConnection
?Почему вывод, когда тип соединения Qt::AutoConnection
отличается от вывода, когда тип соединения прямой и , когда он находится в очереди?Почему это так случайно?
Редактировать: С помощью этого ответа я вижу, что для выполнения слотов, подключенных через соединение с очередями сразу после blockingMap
, цикл события должен быть явно продолжен через вызовqApp->processEvents()
.