что означает слово «ждать» в Rust? - PullRequest
0 голосов
/ 15 февраля 2020

Этот вопрос может в некоторой степени относиться к асинхронному c -программированию, чем к Rust. Но после того, как много гуглить, я думаю, что некоторые моменты отсутствуют. И так как я изучаю Rust, я бы сказал об этом на Rust.

Позвольте мне сначала дать понимание асин c -программирования --- В конце концов, это основа, может быть, я ошибаюсь или нет:

Для эффективной работы программы необходимо одновременное выполнение задач. Затем используется поток, и этот поток можно объединять всякий раз, когда нужны данные из потока. Но поток не достаточно для решения многих задач, как сервер. Затем используется пул потоков, но как извлечь данные, когда они необходимы, без информации о том, какой поток должен ожидать? Затем появляется функция обратного вызова (сокращенно cb). С cb следует учитывать только то, что нужно сделать в cb. Кроме того, чтобы процессор немного нагружался, появляется зеленая нить.

Но что, если асин-ожидающие вещи нужно делать один за другим, что приводит к "адскому обратному вызову"? Хорошо, появляется стиль «будущее / обещание», который позволяет коду выглядеть как syn c -код или, может быть, как цепочка (как в javascript). Но все же код выглядит не совсем красиво. Наконец, появляется стиль "async / await", который является еще одним синтактическим знаком c для стиля "будущее / обещание" И обычно «async / await» со стилем зеленых потоков называется «сопрограммой», будь то использование только одного собственного потока или нескольких собственных потоков над задачами asyn c.

====== =============================================

Насколько я знаю на этом этапе в качестве ключевого слова «await» может использоваться только в области действия «asyn c», и только «asyn c» функция может быть «ожидаемой». Но почему? И к чему он привык, так как уже есть «asyn c»? В любом случае, я тестировал приведенный ниже код:

use async_std::{task};


// async fn easy_task() {
//     for i in 0..100 {
//         dbg!(i);
//     }
//     println!("finished easy task");
// }

async fn heavy_task(cnt1: i32, cnt2: i32) {
    for i in 0..cnt1 {
        println!("heavy_task1 cnt:{}", i);
    }

    println!("heavy task: waiting sub task");
    // normal_sub_task(cnt2);
    sub_task(cnt2).await;
    println!("heavy task: sub task finished");

    for i in 0..cnt1 {
        println!("heavy_task2 cnt:{}", i);
    }
    println!("finished heavy task");
}

fn normal_sub_task(cnt: i32) {
    println!("normal sub_task: start sub task");
    for i in 0..cnt {
        println!("normal sub task cnt:{}", i);
    }
    println!("normal sub_task: finished sub task");
}

async fn sub_task(cnt: i32) {
    println!("sub_task: start sub task");
    for i in 0..cnt {
        println!("sub task cnt:{}", i);
    }
    println!("sub_task: finished sub task");
}

fn outer_task(cnt: i32) {
    for i in 0..cnt {
        println!("outer task cnt:{}", i);
    }
    println!("finished outer task");
}

fn main() {
    // let _easy_f = easy_task();
    let heavy_f = heavy_task(3000, 500);
    let handle = task::spawn(heavy_f);
    print!("=================after spawn==============");
    outer_task(5000);

    // task::join_handle(handle);
    task::block_on(handle);
}

Вывод, который я получил из теста:

1.Не важно ожидать asyn c sub_task или просто делать normal_sub_task (syn c version) в середине asyn c heavy_task (), код ниже (тяжелый l oop task2 ) не будет вырезать строку.

2. Не имеет значения, ожидая asyn c sub_task или просто выполняйте normal_sub_task (syn c version) в середине asyn c heavy_task ( ), external_task иногда обрезается в строке, ломая heavy_task1 или async_sub_task / normal_sub_task.

Поэтому, каково значение слова «await», кажется, что только ключевое слово «asy c» является используется здесь.

ссылка:

asyc_std

sing_dance_example из ржавчины asyncbook

модуль Задача в официальном модуле ржавчины

рекомендуемая статья ржавчины на этой неделе об asyn c -pro грамматика

еще одна статья о ржавчине и асинхронности c -программирование с использованием будущих ящиков

stackoverflow вопрос: Какова цель асинхронизации / ждите в Rust? вывод 2, который я получил, кажется, нарушается против того, что сказал Шепмастер: «... мы чувствовали, что асин c функции должны выполняться синхронно с первым ожиданием».

1 Ответ

2 голосов
/ 15 февраля 2020

Ключевое слово await приостанавливает выполнение асинхронной функции до тех пор, пока ожидаемое будущее (future.await) не выдаст значение.

Это то же значение, что и во всех других языках, использующих концепцию await.

Когда ожидается будущее, «состояние выполнения» функции async сохраняется во внутреннем контексте выполнения, и другие функции asyn c имеют возможность прогрессировать, если они готовы к запуску.

Когда ожидаемое будущее завершается, функция asyn c возобновляется с точной точки приостановки.

Если вы думаете, что мне нужно только async и напишите что-то вроде:

// OK: let result = future.await
let result = future

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

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

Еще несколько комментариев о вашем коде

Вероятно, путаница возникает из-за неправильного понимания концепции задачи.

При изучении асин c в ржавчине я обнаружил asyn c book довольно полезно.

Книга определяет задачи следующим образом:

Задачи - это фьючерсы верхнего уровня, которые были представлены исполнителю

heavy_task - действительно уникальная задача в вашем примере, потому что это единственное будущее, представленное асинхронной среде выполнения с task::block_on.

Например, функция outer_task не имеет ничего общего с асинхронным миром: это не задача, она сразу же вызывается при вызове.

heavy_task ведет себя асинхронно и ожидает sub_task(cnt2) future ... но sub_task futu Один раз выполненный, сразу же завершается.

Таким образом, ваш код ведет себя практически как последовательный.

Но имейте в виду, что в действительности все более тонко, потому что в присутствии других asyn c задачи await внутри heavy_task работает как точка приостановки и дает возможность другим задачам быть выполненными ближе к завершению.

...