Qt C ++ как правильно удалить QFutureWatcher? - PullRequest
0 голосов
/ 04 августа 2020

Мой код иногда дает сбой из-за 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;
}
...