我遇到了非常怪异的错误 - QAction::trigger
导致阻塞对话框出现,导致我的服务器调用trigger
卡住(例如,在对话框关闭之前无法处理套接字信号)。
我想出了一个解决方法。我使用void triggerWorkaround()
将信号QAction::trigger
连接到插槽Qt::QueuedConnection
,然后将其发出:
QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection);
emit triggerWorkaround();
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr);
但这是令人困惑的三行代码。有没有一个非混乱的方法来做到这一点?我发现QMetaObject::invokeMethod
,但坦率地说,这比我目前的解决方案混淆了10倍。另外,我不想将方法名称用作字符串!
答案 0 :(得分:2)
您可以将其分成如下函数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);
}
这将利用临时destroyed()
发出的QObject
信号将排队事件发布到事件循环中。当事件循环处理该事件时,实际上会调用slot / functor。
所以,你可以使用上面这样的函数代替你发布的3行:
QueuedInvoke(targetAction_.data(), &QAction::trigger);
我的回答基于this great answer关于在给定QThread
中执行仿函数的问题。您可以参考它以获取更多详细信息。