微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Qt/C++:在 Qt 事件循环中异步调用方法而不必将其名称写为字符串的最佳方法是什么? 我的解决方案?存在更好的解决方案吗?

如何解决Qt/C++:在 Qt 事件循环中异步调用方法而不必将其名称写为字符串的最佳方法是什么? 我的解决方案?存在更好的解决方案吗?

通常的方式是使用invokeMethod

QMetaObject::invokeMethod(this,"methodName",Qt::QueuedConnection);

工作正常,除了我不想在字符串中编写方法。像以往一样。为什么?因为这是重构的噩梦。想象一下,由于某种原因不得不更改方法名称。软件会出现故障,我必须在 stderr 中注意到该方法不存在。

我的解决方案?

我使用 QTimer。像这样:

QTimer::singleShot(0,this,&ClassName::methodName);

这似乎工作正常。我喜欢这一点的是,您可以用 lambda/bind 替换 &ClassName::methodName 部分,它仍然会绑定到正确的对象(以防我需要将它与 QThread 一起使用),并使用引用我们的预期变量在标准 C++ 中理解:

QTimer::singleShot(0,threadobject,[this,param1,&param2](){ this->methodName(param1,param2); });

存在更好的解决方案吗?

但是...我希望有更好的方法来做到这一点,因为有人阅读我的代码不会理解我为什么在这里使用 QTimer...所以我必须评论所有内容

是否有更好的方法可以兼容低至 5.9 或 5.7 的 Qt 版本?您知道的最佳解决方案是什么?

解决方法

从 Qt 5.10 开始,有 functor-based overloads of QMetaObject::invokeMethod

这意味着您可以放弃基于字符串的方法,而使用现代的 invokeMethod 调用方法。

,

实际上 QTimer 不是解决您问题的异步方法。当当前正在执行的方法退出时,它会将您的方法压入堆栈以调用您的方法。

我认为更好的解决方案是使用 QtConcurrent run。它将以异步方式执行您的方法。

使用起来很简单:

QtConcurrent::run(&myFunc); // some function
QtConcurrent::run(this,&MyClass::method); // for class method
QtConcurrent::run(this,&MyClass::methodWithParams,param1,param2); // for class method with params

此外,您应该像这样将 concurrent 包含到您的 .qmake 文件中:

...
QT += concurrent
...

如果需要函数的结果,可以使用 QFuture 类。

,

这和你已经在做的没什么不同,但我已经通过连接到 QObject 的销毁而不是使用 QTimer 来完成它。

template <typename Func>
void MyClass::runLater(Func &&func)
{
    QObject toBeDestroyed;
    QObject::connect(&toBeDestroyed,&QObject::destroyed,this,func,Qt::QueuedConnection);
}

然后我可以用 lambda 调用它:

void doSomething(const QString &text,int num)
{
    runLater([text,num]() { qDebug() << text << num; });
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。