Класс 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 |
| 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> | onCanceled(QObject *context, Function &&handler) |
| QFuture<T> | onFailed(Function &&handler) |
| QFuture<T> | onFailed(QObject *context, 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) |
| QFuture<ResultType<Function> > | then(QObject *context, Function &&function) |
| void | toggleSuspended() |
| void | waitForFinished() |
Подробное описание
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(), вы сможете подключить несколько продолжений к сигналу, которые будут вызваны в той же нити или новой нити.
Готовый объект QFuture со значением или объект QFuture, содержащий исключение, может быть создан с помощью удобных функций QtFuture::makeReadyFuture и QtFuture::makeExceptionalFuture.
Примечание: Для запуска вычисления и хранения результатов в QFuture используйте QPromise или один из API в рамках фреймворка Qt Concurrent.
См. также QPromise, QtFuture::connect(), QtFuture::makeReadyFuture(), QtFuture::makeExceptionalFuture(), 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().
[since 6.0] bool QFuture::isValid() const
Возвращает true, если к этому объекту QFuture можно получить доступ к результату или результатам. Возвращает false после получения результата из будущего.
Данная функция была представлена в Qt 6.0.
См. также takeResult(), result(), results() и resultAt().
[since 6.0] template <typename Function, typename> QFuture<T> QFuture::onCanceled(Function &&handler)
Прикрепляет обработчик отмены handler к этому будущему, который будет вызываться при отмене будущего. handler — это вызываемый объект без аргументов. Он будет вызван в том же потоке, в котором выполнялось это будущее. Если продолжение прикреплено после того, как родительский элемент уже завершился, оно будет вызвано в потоке, где проживает родитель.
Данная функция была представлена в Qt 6.0.
См. также then() и onFailed().
[since 6.1] template <typename Function, typename> QFuture<T> QFuture::onCanceled(QObject *context, Function &&handler)
Это перегруженная функция.
Прикрепляет обработчик отмены handler к этому будущему, который будет вызываться при отмене будущего. handler — это вызываемый объект без аргументов. Он будет вызван в потоке объекта context. Это может быть полезно, если обработку отмены необходимо выполнить в определённом потоке.
Примечание: При вызове этого метода необходимо гарантировать, что context остаётся активным на протяжении всего выполнения цепочки.
Данная функция была представлена в Qt 6.1.
См. также 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().
[since 6.1] template <typename Function, typename> QFuture<T> QFuture::onFailed(QObject *context, Function &&handler)
Это перегруженная функция.
Прикрепляет обработчик ошибок к этому будущему для обработки любых исключений, которые могут быть сгенерированы. Возвращает QFuture родительского типа. Обработчик будет вызван только в случае исключения в потоке объекта context. Это может быть полезно, если обработку ошибки необходимо выполнить в определённом потоке. Например:
// somewhere in the main thread
auto future = QtConcurrent::run([] {
// This will run in a separate thread
...
throw std::exception();
}).onFailed(this, [] {
// Update UI elements
}); Обработчик ошибок, прикреплённый к QtConcurrent::run, обновляет элементы пользовательского интерфейса и не может быть вызван из потока, отличного от потока пользовательского интерфейса. Поэтому this предоставляется как контекст для .onFailed(), чтобы гарантировать, что он будет вызван в главном потоке.
Примечание: При вызове этого метода необходимо гарантировать, что context остаётся активным на протяжении всего выполнения цепочки.
Данная функция была представлена в Qt 6.1.
См. также 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()
Приостанавливает асинхронное вычисление, представленное этим future. Это удобный метод, который просто вызывает 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), поэтому предполагается, что только один поток может извлечь результаты из future и сделать это только один раз. Также обратите внимание, что извлечение списка всех результатов в данный момент не поддерживается. Тем не менее, вы по-прежнему можете итерировать по списку результатов, которые можно только переместить, используя итераторы в стиле STL или итераторы в стиле Java.
Эта функция была добавлена в Qt 6.0.
См. также result(), results(), resultAt() и isValid().
[since 6.0] template <typename Function> QFuture<ResultType<Function> > QFuture::then(Function &&function)
Это перегруженная функция.
Прикрепляет продолжение к этому future, позволяя при необходимости цепочку нескольких асинхронных вычислений. Когда асинхронное вычисление, представленное этим future, завершается, function будет вызвана в том же потоке, в котором выполнялось это future. Если продолжение прикреплено после того, как родительский элемент уже завершился, он будет вызван в потоке, в котором живёт родительский элемент. Этот метод возвращает новый QFuture, представляющий результат продолжения.
Примечание: Используйте другие перегрузки этого метода, если вам нужно запустить продолжение в отдельном потоке.
Если у этого future есть результат (это не QFuture<void>), function принимает результат этого future в качестве аргумента.
Вы можете цепочкой такие операции:
QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })... Или:
QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })... Продолжение также может принять аргумент QFuture (вместо его значения), представляющий предыдущее future. Это может быть полезно, например, если у QFuture несколько результатов, и пользователь хочет получить к ним доступ внутри продолжения. Или пользователю нужно обработать исключение предыдущего future внутри продолжения, чтобы не прерывать цепочку нескольких продолжений. Например:
QFuture<int> future = ...;
future.then([](QFuture<int> f) {
try {
...
auto result = f.result();
...
} catch (QException &e) {
// handle the exception
}
}).then(...); Если предыдущее future выбрасывает исключение, и оно не обрабатывается внутри продолжения, исключение будет передано в будущее продолжения, чтобы позволить вызывающей стороне его обработать:
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
} В этом случае вся цепочка продолжений будет прервана.
Примечание: Если родительское future отменяется, его продолжения также будут отменены.
Эта функция была добавлена в Qt 6.0.
См. также onFailed() и onCanceled().
[since 6.0] template <typename Function> QFuture<ResultType<Function> > QFuture::then(QtFuture::Launch policy, Function &&function)
Это перегруженная функция.
Прикрепляет продолжение к этому future, позволяя при необходимости цепочку нескольких асинхронных вычислений. Когда асинхронное вычисление, представленное этим future, завершается, 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)
Это перегруженная функция.
Прикрепляет продолжение к этому future, позволяя при необходимости цепочку нескольких асинхронных вычислений. Когда асинхронное вычисление, представленное этим future, завершается, function будет вызвана в отдельном потоке, взятом из QThreadPool pool.
Эта функция была добавлена в Qt 6.0.
См. также onFailed() и onCanceled().
[since 6.1] template <typename Function> QFuture<ResultType<Function> > QFuture::then(QObject *context, Function &&function)
Это перегруженная функция.
Прикрепляет продолжение к этому future, позволяя при необходимости цепочку нескольких асинхронных вычислений. Когда асинхронное вычисление, представленное этим future, завершается, function будет вызвана в потоке объекта context. Это может быть полезно, если продолжению необходимо вызываться в определённом потоке. Например:
// somewhere in the main thread
auto future = QtConcurrent::run([] {
// This will run in a separate thread
...
}).then(this, [] {
// Update UI elements
}); Продолжение, прикреплённое к QtConcurrent::run, обновляет элементы пользовательского интерфейса и не может быть вызвано из потока, не относящегося к пользовательскому интерфейсу. Поэтому this предоставляется в качестве контекста для .then(), чтобы гарантировать, что он будет вызван в главном потоке.
Следующие продолжения также будут вызваны из того же контекста, если не указан другой контекст или политика запуска:
auto future = QtConcurrent::run([] {
...
}).then(this, [] {
// Update UI elements
}).then([] {
// This will also run in the main thread
}); Это происходит потому, что по умолчанию .then() вызывается из того же потока, что и родительский элемент.
Однако обратите внимание, что если продолжение прикреплено после того, как родительский элемент уже завершился, он будет вызван в потоке, в котором живёт родительское future:
QObject *context = ...;
auto parentFuture = cachedResultsReady ? QtFuture::makeReadyFuture(results)
: QtConcurrent::run([] { /* compute results */});
auto future = parentFuture.then(context, [] (Results results) {
// Runs in the context's thread
}).then([] {
// May or may not run in the context's thread
}); В приведённом выше примере, если cachedResultsReady является true, и возвращается готовое future, возможно, что первое .then() завершится до того, как второе будет прикреплено. В этом случае оно будет решено в текущем потоке. Поэтому, когда есть сомнения, явно передавайте контекст.
Примечание: При вызове этого метода должно быть гарантировано, что context остаётся активным в течение всего выполнения цепочки.
Эта функция была добавлена в Qt 6.1.
См. также 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.1/qfuture.html