Spec-Zone.ru › Qt 6.0

Класс QFuture

шаблон <typename T> класс QFuture

Класс QFuture представляет результат асинхронного вычисления. Подробнее...

Заголовок: #include <QFuture>
CMake: find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core
  • Список всех членов, включая унаследованные
  • Устаревшие члены

Примечание: Все функции в этом классе являются потокобезопасными с последующими исключениями:

  • const_iterator

Открытые типы

класс const_iterator
ConstIterator

Открытые функции

QFuture(const QFuture<T> &other)
QFuture()
QFuture<T> & operator=(const QFuture<T> &other)
~QFuture()
QFuture::const_iterator begin() const
void cancel()
QFuture::const_iterator constBegin() const
QFuture::const_iterator constEnd() const
QFuture::const_iterator end() const
bool isCanceled() const
bool isFinished() const
bool isResultReadyAt(int index) const
bool isRunning() const
bool isStarted() const
bool isSuspended() const
bool isSuspending() const
bool isValid() const
QFuture<T> onCanceled(Function &&handler)
QFuture<T> onFailed(Function &&handler)
int progressMaximum() const
int progressMinimum() const
QString progressText() const
int progressValue() const
T result() const
T resultAt(int index) const
int resultCount() const
QList<T> results() const
void resume()
void setSuspended(bool suspend)
void suspend()
T takeResult()
QFuture<ResultType<Function> > then(Function &&function)
QFuture<ResultType<Function> > then(QtFuture::Launch policy, Function &&function)
QFuture<ResultType<Function> > then(QThreadPool *pool, Function &&function)
void toggleSuspended()
void waitForFinished()

Подробное описание

Для запуска вычислений используйте один из API-интерфейсов в рамках фреймворка Qt Concurrent.

QFuture позволяет синхронизировать потоки с одним или несколькими результатами, которые будут готовы в более позднее время. Результат может быть любого типа, имеющего конструкторы по умолчанию, копирования и, возможно, перемещения. Если результат недоступен в момент вызова функций result(), resultAt(), results() и takeResult(), QFuture будет ожидать, пока результат не станет доступным. Вы можете использовать функцию isResultReadyAt() для определения готовности результата. Для объектов QFuture, которые сообщают о более чем одном результате, функция resultCount() возвращает количество непрерывных результатов. Это означает, что всегда безопасно перебирать результаты с 0 до resultCount(). takeResult() делает будущее недействительным, и любые последующие попытки доступа к результату или результатам из будущего приводят к неопределенному поведению. isValid() сообщает вам, можно ли получить доступ к результатам.

QFuture предоставляет итератор в стиле Java (QFutureIterator) и итератор в стиле STL (QFuture::const_iterator). Использование этих итераторов — еще один способ доступа к результатам в будущем.

Если результат одного асинхронного вычисления необходимо передать другому, QFuture предоставляет удобный способ объединения нескольких последовательных вычислений с помощью then(). onCanceled() можно использовать для добавления обработчика, который будет вызываться, если QFuture отменен. Кроме того, onFailed() можно использовать для обработки любых сбоев, произошедших в цепочке. Обратите внимание, что QFuture полагается на исключения для обработки ошибок. Если использование исключений не подходит, вы все равно можете указать состояние ошибки QFuture, сделав тип ошибки частью типа QFuture. Например, вы можете использовать std::variant, std::any или аналогичный тип для хранения результата или ошибки или создать свой собственный тип.

Ниже приведен пример, демонстрирующий, как можно выполнить обработку ошибок без использования исключений. Предположим, что мы хотим отправить сетевой запрос для получения большого файла из сетевого расположения. Затем мы хотим записать его в файловую систему и вернуть его расположение в случае успеха. Обе эти операции могут завершиться ошибкой с различными ошибками. Поэтому мы используем std::variant для хранения результата или ошибки:

using NetworkReply = std::variant<QByteArray, QNetworkReply::NetworkError>;

enum class IOError { FailedToRead, FailedToWrite };
using IOResult = std::variant<QString, IOError>;

И объединяем две операции с помощью then():

QFuture<IOResult> future = QtConcurrent::run([url] {
        ...
        return NetworkReply(QNetworkReply::TimeoutError);
}).then([](NetworkReply reply) {
    if (auto error = std::get_if<QNetworkReply::NetworkError>(&reply))
        return IOResult(IOError::FailedToRead);

    auto data = std::get_if<QByteArray>(&reply);
    // try to write *data and return IOError::FailedToWrite on failure
    ...
});

auto result = future.result();
if (auto filePath = std::get_if<QString>(&result)) {
    // do something with *filePath
else
    // process the error

Можно объединить несколько продолжений и обработчиков в любом порядке. Первый обработчик, который может обработать состояние своего предка, вызывается первым. Если нет соответствующего обработчика, состояние передается следующему продолжению или обработчику. Например:

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
}).onCanceled([] {
    // Block 2
}).onFailed([] {
    // Block 3
}).then([] {
    // Block 4
}).onFailed([] {
    // Block 5
}).onCanceled([] {
    // Block 6
});

Если testFuture успешно выполнится, Block 1 будет вызван. Если оно также выполнится успешно, вызовется следующее then() (Block 4). Если testFuture будет отменен или завершится с ошибкой, соответственно, будут вызваны Block 2 или Block 3. После этого вызовется следующее then(), и история повторится.

Примечание: Если Block 2 вызвана и вызывает исключение, следующее onFailed() (Block 3) обработает его. Если порядок onFailed() и onCanceled() был бы обратным, состояние исключения распространилось бы на следующие продолжения и, в конечном счете, было бы поймано в Block 5.

В следующем примере первое onCanceled() (Block 2) удалено:

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
}).onFailed([] {
    // Block 3
}).then([] {
    // Block 4
}).onFailed([] {
    // Block 5
}).onCanceled([] {
    // Block 6
});

Если testFuture отменяется, его состояние передается следующему then(), которое также будет отменено. Таким образом, в этом случае Block 6 будет вызвано.

QFuture также предлагает способы взаимодействия с выполняемым вычислением. Например, вычисление может быть отменено с помощью функции cancel(). Для приостановки или возобновления вычисления используйте функцию setSuspended() или одну из удобных функций suspend(), resume() или toggleSuspended(). Имейте в виду, что не все выполняемые асинхронные вычисления могут быть отменены или приостановлены. Например, будущее, возвращаемое QtConcurrent::run(), не может быть отменено; но будущее, возвращаемое QtConcurrent::mappedReduced(), может.

Информация о прогрессе предоставляется функциями progressValue(), progressMinimum(), progressMaximum() и progressText(). Функция waitForFinished() заставляет вызывающую нить заблокироваться и дождаться завершения вычисления, гарантируя, что все результаты доступны.

Состояние вычисления, представленного QFuture, можно запросить с помощью функций isCanceled(), isStarted(), isFinished(), isRunning(), isSuspending() или isSuspended().

QFuture — это лёгкий класс со счётом ссылок, который можно передавать по значению.

QFuture<void> специализирован таким образом, чтобы не содержать ни одной из функций извлечения результатов. Любой QFuture<T> может быть присвоен или скопирован в QFuture<void> также. Это полезно, если необходима только информация о состоянии или прогрессе — а не фактические данные результата.

Для взаимодействия с выполняемыми задачами с помощью сигналов и слотов используйте QFutureWatcher.

Вы также можете использовать QtFuture::connect для подключения сигналов к объекту QFuture, который будет разрешён при отправке сигнала. Это позволяет работать с сигналами как с объектами QFuture. Например, если вы объедините его с then(), вы можете прикрепить несколько продолжений к сигналу, которые вызываются в той же нити или новой нити.

См. также QtFuture::connect(), QFutureWatcher и Qt Concurrent.

Документация по типам членов

QFuture::ConstIterator

Синоним Qt-стиля для QFuture::const_iterator.

Документация по функциям-членам

QFuture::QFuture(const QFuture<T> &other)

Создаёт копию other.

См. также operator=().

QFuture::QFuture()

Создаёт пустое, отменённое будущее.

QFuture<T> &QFuture::operator=(const QFuture<T> &other)

Присваивает other этому будущему и возвращает ссылку на это будущее.

QFuture::~QFuture()

Уничтожает будущее.

Обратите внимание, что это не ждёт и не отменяет асинхронное вычисление. Используйте waitForFinished() или QFutureSynchronizer, когда вам нужно убедиться, что вычисление завершено до уничтожения будущего.

template <typename U, typename> QFuture::const_iterator QFuture::begin() const

Возвращает константный STL-стиль итератора, указывающий на первый результат в будущем.

См. также constBegin() и end().

void QFuture::cancel()

Отменяет асинхронное вычисление, представленное этим будущим. Обратите внимание, что отмена асинхронна. Используйте waitForFinished() после вызова cancel(), когда вам нужна синхронная отмена.

Доступные в настоящее время результаты все ещё могут быть обработаны в отменённом будущем, но новые результаты не будут доступны после вызова этой функции. Любой объект QFutureWatcher, отслеживающий это будущее, не будет отправлять сигналы о прогрессе и готовности результата на отменённом будущем.

Обратите внимание, что не все выполняемые асинхронные вычисления могут быть отменены. Например, будущее, возвращаемое QtConcurrent::run(), не может быть отменено; но будущее, возвращаемое QtConcurrent::mappedReduced(), может.

template <typename U, typename> QFuture::const_iterator QFuture::constBegin() const

Возвращает константный STL-стиль итератора, указывающий на первый результат в будущем.

См. также begin() и constEnd().

template <typename U, typename> QFuture::const_iterator QFuture::constEnd() const

Возвращает константный STL-стиль итератора, указывающий на воображаемый результат после последнего результата в будущем.

См. также constBegin() и end().

template <typename U, typename> QFuture::const_iterator QFuture::end() const

Возвращает константный STL-стиль итератора, указывающий на воображаемый результат после последнего результата в будущем.

См. также begin() и constEnd().

bool QFuture::isCanceled() const

Возвращает true , если асинхронное вычисление было отменено с помощью функции cancel(); в противном случае возвращает false.

Обратите внимание, что вычисление может все ещё выполняться, даже если эта функция возвращает true. Смотрите cancel() для более подробной информации.

bool QFuture::isFinished() const

Возвращает true , если асинхронное вычисление, представленное этим будущим, завершено; в противном случае возвращает false.

template <typename U, typename> bool QFuture::isResultReadyAt(int index) const

Возвращает true , если результат в index немедленно доступен; в противном случае возвращает false.

Примечание: Вызов isResultReadyAt() приводит к неопределённому поведению, если isValid() возвращает false для этого QFuture.

См. также resultAt(), resultCount() и takeResult().

bool QFuture::isRunning() const

Возвращает true , если асинхронное вычисление, представленное этим будущим, в настоящее время выполняется; в противном случае возвращает false.

bool QFuture::isStarted() const

Возвращает true , если асинхронное вычисление, представленное этим будущим, было запущено; в противном случае возвращает false.

bool QFuture::isSuspended() const

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

Эта функция была введена в Qt 6.0.

См. также setSuspended(), toggleSuspended() и isSuspending().

bool QFuture::isSuspending() const

Возвращает true , если асинхронное вычисление было приостановлено с помощью функции suspend(), но работа ещё не приостановлена, и вычисление всё ещё выполняется. Возвращает false в противном случае.

Чтобы проверить, действительно ли приостановление в силе, используйте isSuspended() вместо этого.

Эта функция была введена в Qt 6.0.

См. также setSuspended(), toggleSuspended() и isSuspended().

bool QFuture::isValid() const

Возвращает true , если к этому объекту QFuture можно получить доступ к результату или результатам. Возвращает false после того, как результат был взят из будущего.

Эта функция была введена в Qt 6.0.

См. также takeResult(), result(), results() и resultAt().

template <typename Function, typename> QFuture<T> QFuture::onCanceled(Function &&handler)

Присоединяет обработчик отмены к этому будущему, который вызывается, когда будущее отменяется. Обработчик — это вызываемый объект без аргументов. Он будет вызван в том же потоке, в котором работало это будущее. Если продолжение присоединяется после того, как родительский элемент уже завершился, оно будет вызвано в потоке, в котором живёт родитель.

Эта функция была введена в Qt 6.0.

См. также then() и onFailed().

[since 6.0] template <typename Function, typename> QFuture<T> QFuture::onFailed(Function &&handler)

Присоединяет обработчик ошибок к этому будущему для обработки любых исключений, которые могут быть сгенерированы. Возвращает QFuture родительского типа. Обработчик будет вызван только в случае исключения в том же потоке, в котором выполнялось родительское будущее. Если продолжение присоединяется после того, как родительский элемент уже завершился, оно будет вызвано в потоке, в котором живёт родитель. handler — это вызываемый объект, принимающий либо ни одного аргумента, либо один аргумент для фильтрации по определённым типам ошибок, аналогично оператору catch.

Например:

QFuture<int> future = ...;
auto resultFuture = future.then([](int res) {
    ...
    throw Error();
    ...
}).onFailed([](const Error &e) {
    // Handle exceptions of type Error
    ...
    return -1;
}).onFailed([] {
    // Handle all other types of errors
    ...
    return -1;
});

auto result = resultFuture.result(); // result is -1

Если прикреплено несколько обработчиков, будет вызван первый обработчик, соответствующий типу брошенного исключения. Например:

QFuture<int> future = ...;
future.then([](int res) {
    ...
    throw std::runtime_error("message");
    ...
}).onFailed([](const std::exception &e) {
    // This handler will be invoked
}).onFailed([](const std::runtime_error &e) {
    // This handler won't be invoked, because of the handler above.
});

Если ни один из обработчиков не соответствует типу брошенного исключения, исключение будет передано в результирующее будущее:

QFuture<int> future = ...;
auto resultFuture = future.then([](int res) {
    ...
    throw Error("message");
    ...
}).onFailed([](const std::exception &e) {
    // Won't be invoked
}).onFailed([](const QException &e) {
    // Won't be invoked
});

try {
    auto result = resultFuture.result();
} catch(...) {
    // Handle the exception
}

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

Эта функция была введена в Qt 6.0.

См. также then() и onCanceled().

int QFuture::progressMaximum() const

Возвращает максимальное значение progressValue().

См. также progressValue() и progressMinimum().

int QFuture::progressMinimum() const

Возвращает минимальное значение progressValue().

См. также progressValue() и progressMaximum().

QString QFuture::progressText() const

Возвращает (необязательное) текстовое представление прогресса, как сообщается асинхронным вычислением.

Обратите внимание, что не все вычисления предоставляют текстовое представление прогресса, и поэтому эта функция может возвращать пустую строку.

int QFuture::progressValue() const

Возвращает текущее значение прогресса, которое находится между progressMinimum() и progressMaximum().

См. также progressMinimum() и progressMaximum().

template <typename U, typename> T QFuture::result() const

Возвращает первый результат в будущем. Если результат немедленно недоступен, эта функция заблокируется и подождёт, пока результат станет доступным. Это удобный метод для вызова resultAt(0). Обратите внимание, что result() возвращает копию внутреннего хранимого результата. Если T является типом только перемещения, или вы не хотите копировать результат, используйте takeResult() вместо этого.

Примечание: Вызов result() приводит к неопределённому поведению, если isValid() возвращает false для этого QFuture.

См. также resultAt(), results() и takeResult().

template <typename U, typename> T QFuture::resultAt(int index) const

Возвращает результат по индексу index в будущем. Если результат немедленно недоступен, эта функция заблокируется и подождёт, пока результат станет доступным.

Примечание: Вызов resultAt() приводит к неопределённому поведению, если isValid() возвращает false для этого QFuture.

См. также result(), results(), takeResult() и resultCount().

int QFuture::resultCount() const

Возвращает количество непрерывных результатов, доступных в этом будущем. Фактическое число хранимых результатов может отличаться от этого значения из-за пробелов в наборе результатов. Всегда безопасно итерировать по результатам от 0 до resultCount().

См. также result(), resultAt(), results() и takeResult().

template <typename U, typename> QList<T> QFuture::results() const

Возвращает все результаты из будущего. Если результаты немедленно недоступны, эта функция заблокируется и подождёт, пока они станут доступными. Обратите внимание, что results() возвращает копию внутренне хранимых результатов. Получение всех результатов типа только перемещения T в настоящее время не поддерживается. Тем не менее, вы по-прежнему можете итерировать по списку результатов только перемещения с помощью итераторов стиля STL или итераторов стиля Java.

Примечание: Вызов results() приводит к неопределённому поведению, если isValid() возвращает false для этого QFuture.

См. также result(), resultAt(), takeResult(), resultCount() и isValid().

void QFuture::resume()

Возобновляет асинхронное вычисление, представленное будущим. Это удобный метод, который просто вызывает setSuspended(false).

См. также suspend().

[since 6.0] void QFuture::setSuspended(bool suspend)

Если suspend равно true, эта функция приостанавливает асинхронное вычисление, представленное будущим. Если вычисление уже приостановлено, эта функция ничего не делает. QFutureWatcher немедленно не перестанет выдавать сигналы готовности прогресса и результата, когда будущее приостановлено. В момент приостановки всё ещё могут быть вычисления, которые выполняются и не могут быть остановлены. Сигналы для таких вычислений по-прежнему будут передаваться.

Если suspend равно false, эта функция возобновляет асинхронное вычисление. Если вычисление ранее не было приостановлено, эта функция ничего не делает.

Обратите внимание, что не все вычисления могут быть приостановлены. Например, QFuture, возвращаемый QtConcurrent::run(), не может быть приостановлен; но QFuture, возвращаемый QtConcurrent::mappedReduced(), может.

Эта функция была введена в Qt 6.0.

См. также isSuspended(), suspend(), resume() и toggleSuspended().

[since 6.0] void QFuture::suspend()

Приостанавливает асинхронное вычисление, представленное этим будущим. Это удобный метод, который просто вызывает setSuspended(true).

Эта функция была введена в Qt 6.0.

См. также resume().

[since 6.0] template <typename U, typename> T QFuture::takeResult()

Вызывайте эту функцию только если isValid() возвращает true, в противном случае поведение будет неопределённым. Эта функция берёт (перемещает) первый результат из объекта QFuture, когда ожидается только один результат. Если есть другие результаты, они удаляются после извлечения первого. Если результат немедленно недоступен, эта функция заблокируется и подождёт, пока результат станет доступным. QFuture попытается использовать семантику перемещения, если это возможно, и вернётся к копированию по построению, если тип не перемещаем. После того, как результат был взят, isValid() будет оцениваться как false.

Примечание: QFuture в целом позволяет совместно использовать результаты между различными объектами QFuture (и потенциально между разными потоками). takeResult() была введена, чтобы QFuture также работал с типами только перемещения (например, std::unique_ptr), поэтому она предполагает, что только один поток может переместить результаты из будущего и сделать это только один раз. Также обратите внимание, что получение списка всех результатов в настоящее время не поддерживается. Тем не менее, вы по-прежнему можете итерировать по списку результатов только перемещения с помощью итераторов стиля STL или итераторов стиля Java.

Эта функция была введена в Qt 6.0.

См. также result(), results(), resultAt() и isValid().

[since 6.0] template <typename Function> QFuture<ResultType<Function> > QFuture::then(Function &&function)

Это перегруженная функция.

Присоединяет продолжение к этому будущему, позволяя при необходимости объединять несколько асинхронных вычислений. Когда асинхронное вычисление, представленное этим будущим, завершается, функция будет вызвана в той же нити, в которой выполнялось это будущее. Если продолжение присоединено после того, как родительский элемент уже завершился, оно будет вызвано в нити, где находится родитель. Этот метод возвращает новое QFuture, представляющее результат продолжения.

Примечание: Используйте другие перегрузки этого метода, если вам нужно запустить продолжение в отдельной нити.

Если у этого будущего есть результат (не является QFuture<void>), функция принимает результат этого будущего в качестве аргумента.

Вы можете объединить несколько операций следующим образом:

QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })...

Или:

QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })...

Продолжение также может принимать аргумент QFuture (вместо его значения), представляющий предыдущее будущее. Это может быть полезно, например, если QFuture имеет несколько результатов, и пользователь хочет получить доступ к ним внутри продолжения. Или пользователю необходимо обработать исключение предыдущего будущего внутри продолжения, чтобы не прерывать цепочку нескольких продолжений. Например:

QFuture<int> future = ...;
    future.then([](QFuture<int> f) {
        try {
            ...
            auto result = f.result();
            ...
        } catch (QException &e) {
            // handle the exception
        }
    }).then(...);

Если предыдущее будущее вызывает исключение, и оно не обрабатывается внутри продолжения, исключение будет передано в будущее продолжения, чтобы позволить вызывающей стороне обработать его:

QFuture<int> parentFuture = ...;
auto continuation = parentFuture.then([](int res1){ ... }).then([](int res2){ ... })...
...
// parentFuture throws an exception
try {
    auto result = continuation.result();
} catch (QException &e) {
    // handle the exception
}

В этом случае вся цепочка продолжений будет прервана.

Примечание: Если родительское будущее отменяется, его продолжения также будут отменены.

Эта функция была представлена в Qt 6.0.

См. также onFailed() и onCanceled().

[since 6.0] template <typename Function> QFuture<ResultType<Function> > QFuture::then(QtFuture::Launch policy, Function &&function)

Это перегруженный метод.

Присоединяет продолжение к этому будущему, позволяя объединять несколько асинхронных вычислений. Когда асинхронное вычисление, представленное этим будущим, завершается, функция вызывается в соответствии с заданной политикой запуска policy. Возвращается новое QFuture, представляющее результат продолжения.

В зависимости от policy, продолжение будет выполняться в той же нити, что и родительское, в новой нити или унаследует политику запуска и пул потоков родительского.

В следующем примере оба продолжения будут выполняться в новой нити (но в одной и той же).

QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... }).then([](int res2){ ... });

В следующем примере оба продолжения будут выполняться в новых нитях с использованием одного и того же пула потоков.

QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... })
      .then(QtFuture::Launch::Inherit, [](int res2){ ... });

Эта функция была представлена в Qt 6.0.

См. также onFailed() и onCanceled().

[since 6.0] template <typename Function> QFuture<ResultType<Function> > QFuture::then(QThreadPool *pool, Function &&function)

Это перегруженный метод.

Присоединяет продолжение к этому будущему, позволяя при необходимости объединять несколько асинхронных вычислений. Когда асинхронное вычисление, представленное этим будущим, завершается, функция будет вызвана в отдельной нити, взятой из QThreadPool pool.

Эта функция была представлена в Qt 6.0.

См. также onFailed() и onCanceled().

[since 6.0] void QFuture::toggleSuspended()

Переключает состояние приостановки асинхронного вычисления. Другими словами, если вычисление в настоящее время приостанавливается или приостановлено, вызов этой функции возобновляет его; если вычисление выполняется, оно приостанавливается. Это удобный метод для вызова setSuspended(!(isSuspending() || isSuspended())).

Эта функция была представлена в Qt 6.0.

См. также setSuspended(), suspend() и resume().

void QFuture::waitForFinished()

Ожидает завершения асинхронного вычисления (включая отменённые вычисления), т.е. до тех пор, пока isFinished() не вернёт true.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qfuture.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API