I want to invoke a slot of 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*/
};
But because in my case boost::asio
use, with threads I don't want to have to do anything with Qt, I want to invoke this slot from a thread different from the main thread but a random thread I don't control. (On of the threads I let run boost::asio
of course)
How can I do this? QCoreApplication::postEvent
seems to be a nice choice, but the docs don't point out a nice way, on how to create the necessary QEvent
. QMetaObject::invokeMethod
with Qt::QueuedConnection
seems nice too, but isn't documented as thread safe.
So how can I safely invoke a qt slot from a non qt managed thread?
(Although the title of Boost asio with Qt suggests this could be a duplicate, the question seems completely different to me, this questions is not necessarily connected to boost::asio
)
Turns out QMetaObject::invokeMethod
with Qt::QueuedConnection
actually uses QCoreApplication::postEvent
in its implementation (Thanks @peppe!). However the guarantee that it is thread safe, when
Qt::QueuedConnection
is not documented, yet. But I have created a bug report and qt forum discussion, and it seems it was intended to be so, and a documentation change ticket is already been created.
What I used in the end is the common pattern
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))
);
}