Как согласовать асинхронный API с API, который требует синхронности?

Этот вопрос проистекает из вопрос Я спрашивал ранее.

Короче говоря, абстрактный класс поставщика изображений требует реализации метода, который запрашивает изображение через параметр «url» и возвращает изображение. Например. один метод запрашивает и возвращает изображение. Но Qt’s QNetworkAccessManager класс предназначен исключительно для асинхронного использования, например Вы запрашиваете URL одним методом и перехватываете его, подключаясь к сигналу, излучаемому после завершения запроса. Например. Это должно быть разбито на два шага, в связи с чем возникает вопрос: как реализовать провайдер изображения, требующий единственного метода с классом, который должен был быть разбит (учитывая, что взлом, который я использовал, чтобы заставить его быть синхронным, привел к бардак)?

2

Решение

Общий ответ: это не может быть безопасно сделано. В определенных случаях, однако, это может быть сделано, но это требует тщательного изучения кода и некоторого доказательства отсутствия проблем из-за повторного входа.

Что касается использования синхронного класса, вам просто нужно запустить локальный цикл событий внутри requestXxxx реализация метода. Если он выполняется в выделенном потоке, то проблемы повторного входа являются меньшей проблемой, так как вы контролируете, какие объекты активны в потоке.

Так как ваша реализация QQuickImageProvider можно указать ForceAsynchronousImageLoading флаг, ваш провайдер будет работать в своем собственном потоке и может безопасно запустить свой собственный цикл обработки сообщений.

Обратите внимание, что поставщик изображений QML по умолчанию принимает URI в качестве входных данных и будет рад загрузить изображения из Интернета — поэтому вам не нужно беспокоиться об этом в этом случае.

Таким образом, даже через ваш собственный поставщик изображений совершенно не нужно, если бы вы его создали, вот как вы можете это сделать:

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;
}
2

Другие решения


По вопросам рекламы [email protected]