2

我遇到了非常奇怪的错误 -QAction::trigger导致出现阻塞对话框,这导致我调用trigger的服务器卡住(例如,在对话框关闭之前无法处理套接字信号)。

我想出了一个解决方法。我使用将信号连接void triggerWorkaround()到插槽并发出它:QAction::triggerQt::QueuedConnection

QObject::connect(this, &HackClass::triggerWorkaround, targetAction_.data(), &QAction::trigger, Qt::QueuedConnection);
emit triggerWorkaround();
QObject::disconnect(this, nullptr, targetAction_.data(), nullptr);

但这是三行令人困惑的代码。有没有一种不混淆的方法来做到这一点?我发现QMetaObject::invokeMethod,但坦率地说,这比我目前的解决方案更令人困惑 10 倍。另外,我不想将方法名称用作字符串!

4

1 回答 1

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);

我的回答是基于这个关于在给定的QThread. 您可以参考它以获取更多详细信息。

于 2017-01-28T13:52:43.977 回答