Вызовите слот Qt безопасным из потока не-qt - PullRequest
0 голосов
/ 16 декабря 2018

Я хочу вызвать слот MyWidget

class MyWidget : public QWidget {
Q_OBJECT

public slots:
void onFooBar(const std::string&);/*std::string& could also be replaced
    by a QString for easier meta system handling*/
};

Но поскольку в моем случае boost::asio используется, с потоками, я не хочу ничего делать с Qt, я хочувызвать этот слот из потока, отличного от основного потока, но случайного потока, который я не контролирую.(Конечно, из одного потока я запускаю boost::asio)

Как я могу это сделать?QCoreApplication::postEvent кажется хорошим выбором, но в документах не указано, как создать необходимый QEvent.QMetaObject::invokeMethod с Qt::QueuedConnection тоже неплохо, но не документировано как поточно-безопасное.

Так как я могу безопасно вызвать слот qt из потока, не управляемого qt?

(Хотя название Boost asio с Qt предполагает, что это может быть дубликатом, вопрос кажется мне совершенно другим, эти вопросы не обязательно связаны с boost::asio)

1 Ответ

0 голосов
/ 16 декабря 2018

Получается QMetaObject::invokeMethod с Qt::QueuedConnection, на самом деле использует QCoreApplication::postEvent в своей реализации (Спасибо, @peppe!).Однако гарантия того, что он является поточно-ориентированным, когда

  1. используется с Qt::QueuedConnection
  2. Время жизни получателя, управляемого Qt (или AFAIK, по крайней мере, до завершения вызова)
  3. Никаких других действий с получателем, кроме подобных, из неосновного потока qt
  4. Время жизни параметров, управляемых Qt (должно быть хорошо при использовании Q_ARS или при вызове по значению)

пока не задокументировано.Но я создал отчет об ошибке и qt forum обсуждение, и похоже, что так оно и было, и заявка на изменение документации уже создана.

В конце концов я использовал общий шаблон

class MyWidget : public QWidget {
Q_OBJECT

public slots:
void onFooBar(QString);
};

void asio_handler(const std::string& string, MyWidget* my_widget) {
QMetaObject::invokeMethod(
                        my_widget, "onFooBar", Qt::QueuedConnection,
                        Q_ARG(QString, QString::fromStdString(string))
                        );
}
...