Как я могу изменить значение переменной из асин c блока, не вступая во владение им - PullRequest
0 голосов
/ 29 марта 2020

Я довольно новичок в ржавчине, пытаюсь сделать небольшую игру с веб-сборкой, используя rust и wasm-bindgen. У меня есть прослушиватель событий, который прослушивает нажатия клавиш и возвращает направление через поток. Затем я хочу рисовать что-то в элементе canvas каждые 500 мсек, основываясь на значении переменной direction.

Моя проблема в том, что я не могу изменить переменную direction из блока asyn c и используйте его в замыкании Interval.

Использование ключевого слова move в блоке asyn c и замыкании Interval приводит к компиляции кода, но направление никогда не изменяется внутри функции интервала. Я думаю, что переменная направления затем копируется в блок / закрытие, поскольку перечисление Direction реализует черту Copy.

Я включил упрощенную версию своей функции точки входа:

#[wasm_bindgen]
pub fn run() -> Result<(), JsValue> {
    let mut direction = Direction::Right;

    let fut = async {
        let mut on_key_down = EventListenerStruct::new();

        while let Some(dir) = on_key_down.next().await {
            direction = dir;
          // ^^^^^^^^ this errors because direction does not live long enough
          // argument requires that `direction` is borrowed for `static`
        }
    };
    spawn_local(fut);

    Interval::new(500, || {
        // I want to use direction here
    })
    .forget();

    Ok(())
}

У меня вопрос; Могу ли я позаимствовать переменную в блок asyn c? И можно ли заставить его жить достаточно долго, не завладев им?

Заранее спасибо,

1 Ответ

1 голос
/ 22 апреля 2020

Да, вы можете сделать это, используя Ar c и Mutex.

use std::sync::{Arc, Mutex};

fn main() {
    let mut direction = Arc::new(Mutex::new(Direction::Right));

    let direction2 = Arc::clone(&direction);
    let fut = async {
        let mut on_key_down = EventListenerStruct::new();

        while let Some(dir) = on_key_down.next().await {
            *direction2.lock().unwrap() = dir;
        }
    };
    spawn_local(fut);

    Interval::new(500, || {
        let direction = direction.lock().unwrap();
    })
    .forget();
}
...