Мой код иногда дает сбой из-за asyn в будущем c.
Это не производственный код, а просто очень простой материал для демонстрации того, что я хочу сделать.
Мне нужно скачать info, а затем вернуть первый полученный результат. Только представьте, что я не хочу ждать, поэтому я использую QFutureWatcher
, слишком ускоряю загрузку.
Когда я получил результат (first
или второй instance
), я хочу вернуть результат НЕМЕДЛЕННО (я имею в виду, что не хочу использовать QFutureWatcher::waitForFinished
. (Если я получил готовый сигнал от экземпляра first
, мне больше не нужен second
. Или то же самое для first
.
В производственной функции кода download
я не могу получить доступ к QNetworkReply
, поэтому ожидающий запрос не может быть прерван.
Иногда происходит сбой этого кода. Что я делаю не так?
#include <QFutureWatcher>
#include <QtConcurrent>
#include <QEventLoop>
#include <QTimer>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
QByteArray download(const QUrl &url)
{
QNetworkAccessManager manager;
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::SynchronousRequestAttribute, true);
QNetworkReply *reply = manager.get(req);
reply->deleteLater();
return reply->readAll();
}
QByteArray downloadSmth(const QUrl &urlFirst, const QUrl &urlSecond)
{
typedef QFutureWatcher<QByteArray> FutureWatcher;
FutureWatcher *first = new FutureWatcher;
FutureWatcher *second = new FutureWatcher;
QByteArray res;
QEventLoop loop;
QObject::connect(first, &FutureWatcher::finished, [&res, &loop, first] {
res = first->result();
loop.quit();
});
QObject::connect(second, &FutureWatcher::finished, [&res, &loop, second] {
res = second->result();
loop.quit();
});
QTimer timer;
timer.setSingleShot(true);
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
first->setFuture(
QtConcurrent::run([&urlFirst] {
return download(urlFirst);
}));
second->setFuture(
QtConcurrent::run([&urlSecond] {
return download(urlSecond);
}));
timer.start(60 * 1000);
loop.exec();
if (timer.isActive()) {
timer.stop();
}
first->deleteLater();
second->deleteLater();
return res;
}