我有一个基于循环的GUI应用程序。循环的运行频率可能比每一帧都要高,因此它必须轻巧。有时需要完成繁重的工作。我不确定如何实现。我在想像这样的东西:
adoRS(KickOtherDesc)
以上示例基于linked answer's tokio-threadpool example。该示例具有如下数据流:
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!()
}
该示例与我的案例之间的主要区别在于任务let a = delay_for(3);
let b = delay_for(1);
let sum = a.join(b).map(|(a, b)| a + b);
触发任务a
,并且当b
完成时b
传递了a
的结果并继续工作。它将重复多次。
我觉得我正在尝试以一种不是Rust中惯用的异步编程的方式来实现这一目标。
如何在后台运行该工作负载?还是用上面的代码表述:我如何在b
中并行执行Future?如果我的方法确实严重偏离轨道,您能朝正确的方向轻推我吗?