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

The*_*ist 5 c++ qt asynchronous c++11 qt5

正常的方法是invokeMethod

QMetaObject::invokeMethod(this, "methodName", Qt::QueuedConnection);
Run Code Online (Sandbox Code Playgroud)

效果很好,只是我不想在字符串中编写方法。像以前一样。为什么?因为这是一场重构噩梦。想象一下由于某种原因必须更改方法名称。软件将发生故障,我必须在 stderr 中注意到该方法不存在。

我的解决方案?

我用的是QTimer。像这样:

QTimer::singleShot(0, this, &ClassName::methodName);
Run Code Online (Sandbox Code Playgroud)

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

QTimer::singleShot(0, threadObject, [this, param1, &param2](){ this->methodName(param1, param2); });
Run Code Online (Sandbox Code Playgroud)

存在更好的解决方案吗?

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

有没有更好的方法来做到这一点,并且与低至 5.9 或 5.7 的 Qt 版本兼容?您知道的最佳解决方案是什么?

Fly*_*ole 0

实际上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
Run Code Online (Sandbox Code Playgroud)

另外,您应该在文件中包含并发.qmake,如下所示:

...
QT += concurrent
...
Run Code Online (Sandbox Code Playgroud)

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