这个问题源于我之前问过的question

简而言之,图像提供者抽象类需要一个实现一种方法,该方法通过参数“url”请求图像并返回图像。例如。一个方法请求并返回图像。但是Qt的QNetworkAccessManager类严格设计用于异步使用,例如您可以通过一种方法来请求url,并通过连接到请求完成后发出的信号来拦截它。例如。它必须分两步进行分解,这引发了一个问题,即如何去实现图像提供程序所需的单一方法以及一个旨在被分解的类(考虑到我用来强制其同步的hack导致一团糟)?

最佳答案

普遍的答案是:这不能安全地完成。虽然在特定情况下可以做到,但是它需要仔细检查所涉及的代码,并提供一些证据证明不会由于重入而出现问题。

至于使用同步类,您只需要在requestXxxx方法的实现内运行本地事件循环。如果它在专用线程中运行,那么重入问题就不那么重要了,因为您可以控制线程中哪些对象处于 Activity 状态。

由于您的QQuickImageProvider实现可以指定ForceAsynchronousImageLoading标志,因此您的提供程序将在其自己的线程中运行,并且可以安全地运行其自己的消息循环。

请注意,默认的QML图像提供程序将URI作为输入,并且非常乐意从Web加载图像-因此,在这种情况下,您不必担心。

因此,即使通过自定义图像提供程序也完全没有必要,但是如果要创建它,则可以按照以下方法进行操作:

class MyImageProvider : public QQuickImageProvider {
public:
  MyImageProvider();
  Flags flags() const { return ForceAsynchronousImageLoading; }
  QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize)
    Q_DECL_OVERRIDE;
}

QImage MyImageProvider::requestImage(
  const QString & id, QSize * size, const QSize & requestedSize)
{
  QImage image;
  QEventLoop loop;
  QNetworkAccessManager mgr;
  QObject::connect(&mgr, &QNetworkAccessManager::finished,
    [&loop, size](QNetworkReply* reply) {
       image.load(reply, "JPG");
       if (size) *size = image.size();
       loop.quit();
       delete reply;
    });
  mgr.get(QNetworkRequest(QUrl(id)));
  loop.exec();
  return image;
}

关于c++ - 如何使异步API符合要求同步的API?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25937975/

10-16 04:15