Оболочка сигналов и слотов pthread 2 с QEventLoop

В настоящее время я ставлю FUSE вместе с qt5. между Qt и FUSE нет моста, и основной поток FUSE (который порождает другие рабочие потоки FUSE) и QCoreApplication просто работают бок о бок.

но я хочу иметь возможность отправлять и получать данные между объектом, основанным на QObject, и функцией чтения (..) pthread, показанной в [0], с использованием SIGNALS и SLOTS в Qt.

Теперь я хочу изменить функцию Read (..) из [0] для получения данных, используя SIGNALS и SLOTS в Qt из класса, основанного на QObject. отправка сигнала из pthread работает, но без явного QEventLoop я не могу получить ответ. поэтому я искал код из [1], который превосходен по дизайну, но я пока не получил его работу.

псевдокод (взят из [1]):

QNetworkAccessManager qnam;
QNetworkReply *reply = qnam.get(QNetworkRequest(QUrl(...)));
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
/* reply has finished, use it */

выглядит интересно, все, что мне нужно, это производный класс QObject, похожий на QNetworkReply, который будет обрабатывать запрос.

когда я играл с этим кодом, у меня возникла проблема, заключающаяся в том, что моя реализация QNetworkReply не дожидалась запуска loop.exec (), и тогда SIGNAL готового () сигнала не был бы получен циклом.

но разве нет ничего проще, чем создать QEventLoop?

НОТА: QNetworkReply и QNetworkAccessManager в примере из [1] создаются внутри pthread, однако мне необходимо иметь возможность связываться с четной очередью QCoreApplication, используя SIGNALS и SLOTS, поскольку объект с данными в нем поступает из другого QThread (в это либо QCoreApplication, либо специальный QThread).

я также нашел [2] и возможно:

connect (src, SIGNAL (сигнал-подпись), dest, SLOT (слот-подпись), Qt :: QueuedConnection);

это все, что я хочу, но я сомневаюсь в этом.

1

Решение

То, что вы, вероятно, сталкиваетесь с тем, что QNetworkAccessManager внутренне использует потоки для обработки http-запросов. Вот почему это «не ждет» вас. Для ее исправления требуется довольно простая модификация:

QNetworkAccessManager qnam;
QEventLoop loop;
QNetworkReply *reply = qnam.get(QNetworkRequest(QUrl(...)));
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
if (!reply->isFinished()) loop.exec();

На что следует обратить внимание при использовании объектов QObject в нескольких потоках

Когда объект, являющийся источником сигнала, живет (создается в) в потоке, отличном от потока объекта со слотами, соединение будет QueuedConnection введите автоматически.

Настоящая проблема: каждый QObject имеет сродство потока. Сходство по умолчанию — это поток, в котором был создан объект. Вы не должны использовать такие объекты непосредственно из других потоков.

Скорее всего, вы создаете экземпляры объектов отправителя и получателя в одном потоке, но затем излучаете сигнал из другого потока. Это источник ошибок потенциальных ошибок и приводит к неопределенному поведению, если пользователь таким объектом является принудительное неавтоматическое прямое соединение.

Всякий раз, когда вы делаете emit object->signal(...)должен иметь место следующий инвариант:

Q_ASSERT(QThread::currentThread() == object->thread());

Не стесняйтесь добавлять эти инвариантные проверки перед каждым emit() что вы явно выполняете.

Если утверждение не удалось, вам нужно использовать QObject::moveToThread переместить объект в поток, где вы хотите запустить его сигналы. Вы можете получить QThread для данного pthread позвонив QThread::currentThread() из кода, который работает в pthread, Экземпляр QThread будет создан автоматически для вас 🙂

0

Другие решения

Да, вам нужен метод Qt :: QueuedConnection. Но также убедитесь, что вы используете многопоточную библиотеку Qt. IIRC это вариант времени сборки.

Смотрите также: Документация Qt

0

По вопросам рекламы [email protected]