Как запустить рабочую нагрузку в фоновом режиме? - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть приложение с графическим интерфейсом, которое основано на цикле.Цикл может выполняться чаще, чем каждый кадр, поэтому он должен быть легким.Есть большая нагрузка, которую нужно делать время от времени.Я не уверен, как это реализовать.Я представляю себе что-то вроде:

extern crate tokio; // 0.1.7
extern crate tokio_threadpool; // 0.1.2

use std::{thread, time::Duration};
use tokio::{prelude::*, runtime::Runtime};

fn delay_for(
    seconds: u64
    ) -> impl Future<Item = u64, Error = tokio_threadpool::BlockingError> 
{
    future::poll_fn(move || {
        tokio_threadpool::blocking(|| {
            thread::sleep(Duration::from_secs(seconds));
            seconds
        })
    })
}

fn render_frame(n: i8) {
    println!("rendering frame {}", n);
    thread::sleep(Duration::from_millis(500));
}

fn send_processed_data_to_gui(n: i8) {
    println!("view updated. result of background processing was {}", n);
}

fn main() {
    let mut frame_n = 0;
    let frame_where_some_input_triggers_heavy_work = 2;
    let mut parallel_work: Option<BoxedFuture> = None;
    loop {
        render_frame(frame_n);
        if frame_n == frame_where_some_input_triggers_heavy_work {
            parallel_work = Some(execute_in_background(delay_for(1)));
        }

        // check if there's parallel processing going on
        // and handle result if it's finished
        parallel_work
            .take()
            .map(|parallel_work| {
                if parallel_work.done() {
                    // giving result back to app
                    send_processed_data_to_gui(parallel_work.result())
                }
            });

        frame_n += 1;
        if frame_n == 10 {
            break;
        }
    }
}

fn execute_in_background(work: /* ... */) -> BoxedFuture {
    unimplemented!()
}

Ссылка на игровую площадку

Приведенный выше пример основан на примере tokio-threadpool связанного ответа .В этом примере поток данных выглядит следующим образом:

let a = delay_for(3);
let b = delay_for(1);
let sum = a.join(b).map(|(a, b)| a + b); 

Основное различие между этим примером и моим делом состоит в том, что задача a запускает задачу b, а когда b завершается, a проходитрезультат b и продолжает работать.Это также будет повторяться любое количество раз.

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

Как запустить эту рабочую нагрузку вфон?Или перефразировать в терминах наброска кода выше: как мне выполнить будущее в parallel_work параллельно?Если мой подход действительно сильно отклоняется от курса, можете ли вы подтолкнуть меня в правильном направлении?

...