task: Выполнение Future и освобождение ресурсов

Описывает однократное использование, выполнение и отмену асинхронных операций после очистки.

Wave Foundation

Базовый API

Импортировано как import("std::task" as task);.

block_on<T>(future: Future<T>) -> T
spawn<T>(future: Future<T>) -> Future<T>
cancel<T>(future: Future<T>) -> bool
yield_now() -> Future<void>
sleep_ms(milliseconds: i64) -> Future<void>
cancel_and_join<T>(future: Future<T>) -> Future<void>
shutdown()

task::block_on(pending) выполняется до тех пор, пока Future не завершится и не вернет результат. Тип результата определяется из переданного Future.

правила жизни

Future — это дескриптор одноразового потребления. Я не рассматриваю копирование значений как две независимые операции. Вы также несете ответственность за ожидание результатов или отмену/организацию задач, запланированных с помощью spawn. Future уже использован с await и block_on не будет использован снова.

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

совместное исполнение

Длительные вычисления и синхронные вызовы blocking могут замедлить общий прогресс исполнителя. Асинхронное ожидание с yield дает возможность выполнения. Блокировка I/O не становится асинхронной только потому, что она находится внутри функции async.

Посмотрите последовательность выполнения и очистки в полной программе в Введение в асинхронный код.

Уступить и дождаться завершения

Следующая программа завершает выполнение в середине операции и возвращает результат. Поскольку yield не является завершением функции, код после await выполняется непрерывно.

import("std::task" as task);

async fun calculate() -> i32 {
    println("started");
    await task::yield_now();
    println("resumed");
    return 42;
}

fun main() -> i32 {
    var pending: Future<i32> = calculate();
    var result: i32 = task::block_on(pending);

    println("result={}", result);
    task::shutdown();
    return 0;
}

Результат выполнения:

started
resumed
result=42

В этом примере нет других операций, поэтому порядок вывода одинаков. В программе, имеющей несколько задач spawn, другие задачи могут выполняться в точке yield, поэтому это не зависит от порядка вывода различных задач.

Порядок организации задач

  1. Подготовьте место для хранения и ресурсы, необходимые для работы.
  2. Создайте Future и запустите его как await, block_on или spawn.
  3. Если вам нужны результаты, дождитесь завершения.
  4. Если вы отменили выполняемую задачу, подождите, пока она очистится.
  5. Очищает буферы, файлы и сокеты, заимствованные задачей.
  6. Если работы не осталось, позвоните по номеру shutdown.

Future Выход из области действия переменной — это одно, а безопасная очистка работы — это другое. В частности, если вы передаете задаче адрес локального массива функции async, задача должна завершить использование этого массива до того, как функция вернется.

async Функции разделения и общие функции

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

Вы можете сравнить создание и запуск Future с асинхронное обучение.