使用清晰的代码行异步调用插槽而不连接到它
Invoke slot asynchronously without connecting to it using clear line of code
我遇到了非常奇怪的错误 - QAction::trigger
导致出现阻塞对话框,这导致调用 trigger
的服务器卡住(例如,在对话框关闭之前无法处理套接字信号).
我找到了解决方法。我使用 Qt::QueuedConnection
将信号 void triggerWorkaround()
连接到插槽 QAction::trigger
并发出它:
QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection);
emit triggerWorkaround();
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr);
但这是三行令人困惑的代码。有没有一种不混淆的方法来做到这一点?我找到了 QMetaObject::invokeMethod
,但坦率地说,这比我当前的解决方案混乱 10 倍。另外,我不想将方法名称用作字符串!
您可以将其拆分为函数 QueuedInvoke
,如下所示:
//overload for methods/slots
//the slot gets invoked in the thread where the QObject lives
template <typename Object, typename T>
void QueuedInvoke(Object* object, T (Object::* f)()){
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed,
object, f, Qt::QueuedConnection);
}
//overload for functors
//the functor gets invoked in the thread where the contextObject lives
//or in the current thread if no contextObject is provided
template <typename Func>
void QueuedInvoke(Func&& f, QObject* contextObject = QAbstractEventDispatcher::instance()){
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed,
contextObject, std::forward<Func>(f), Qt::QueuedConnection);
}
这将利用从临时 QObject
发出的 destroyed()
信号到 post 排队事件进入事件循环。 slot/functor 在事件循环处理该事件时实际被调用。
因此,您可以像这样使用上面的函数,而不是您 post 编辑的 3 行:
QueuedInvoke(targetAction_.data(), &QAction::trigger);
我的回答是基于 this great answer 关于在给定的 QThread
中执行仿函数。详情可以参考
我遇到了非常奇怪的错误 - QAction::trigger
导致出现阻塞对话框,这导致调用 trigger
的服务器卡住(例如,在对话框关闭之前无法处理套接字信号).
我找到了解决方法。我使用 Qt::QueuedConnection
将信号 void triggerWorkaround()
连接到插槽 QAction::trigger
并发出它:
QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection);
emit triggerWorkaround();
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr);
但这是三行令人困惑的代码。有没有一种不混淆的方法来做到这一点?我找到了 QMetaObject::invokeMethod
,但坦率地说,这比我当前的解决方案混乱 10 倍。另外,我不想将方法名称用作字符串!
您可以将其拆分为函数 QueuedInvoke
,如下所示:
//overload for methods/slots
//the slot gets invoked in the thread where the QObject lives
template <typename Object, typename T>
void QueuedInvoke(Object* object, T (Object::* f)()){
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed,
object, f, Qt::QueuedConnection);
}
//overload for functors
//the functor gets invoked in the thread where the contextObject lives
//or in the current thread if no contextObject is provided
template <typename Func>
void QueuedInvoke(Func&& f, QObject* contextObject = QAbstractEventDispatcher::instance()){
QObject signalSource;
QObject::connect(&signalSource, &QObject::destroyed,
contextObject, std::forward<Func>(f), Qt::QueuedConnection);
}
这将利用从临时 QObject
发出的 destroyed()
信号到 post 排队事件进入事件循环。 slot/functor 在事件循环处理该事件时实际被调用。
因此,您可以像这样使用上面的函数,而不是您 post 编辑的 3 行:
QueuedInvoke(targetAction_.data(), &QAction::trigger);
我的回答是基于 this great answer 关于在给定的 QThread
中执行仿函数。详情可以参考