Rust
异步编程浅悟(一)
不同于javascript
的new Promise((resolve, reject) => {...})
构造即运行,Rust
中的Future
是·惰性·状态机。这体现为:
- 【调用异步函数】或【执行异步块】仅只构造一个
Future trait object
。 - 因为
Future
是惰性状态机,所以它不会自动执行【异步函数】或【异步块】内的任何一行代码 --- 此点与javascript
的·活性·状态机完全不同。相反,需要人工激活触发。 - 人工启动
Future
运行,又分为两个场景的两种情况:-
已经在
async fn
内,Future.await
激活。但,同时阻塞当前异步程序执行流。 -
在
async fn
外,需要借助由【运行时】提供的【执行器】。就async-std
库而言,有两个选择:task::block_on(Future)
执行Future
且阻塞当前线程直到Future
被完成。task::spawn(Future)
仅执行Future
和不阻塞当前线程。
无论选择上面哪种方式,若在
Future
执行期间出现了panic
,其都会终止(abort
)正在共享同一个执行线程(thread
)的所有task
(·无栈·协程)的运行。
-
题外话,
- 绿色线程是·有栈·协程;异步函数与异步块是·无栈·协程。
- 在
async-std
库的词汇表内,协程被称作task
而不是惯例的coroutine
。 task::spawn(Future)
也能被使用于async fn
或async {...}
内。它被用来代替.await
指令,以非阻塞async fn
或async {...}
的方式,激活与执行一个Future
实例。
例程
async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> {
// 1. TcpListener::bind(addr) 返回 Future
// 2. .await 于 Future 取得 Result<T, E>
// 3. Result<T, E>? 再拿得 Ok<T> 中的 T
let listener = TcpListener::bind(addr).await?; // 异步函数内的人工启动 Future
let mut incoming = listener.incoming();
// 因为没有从语言层面支持 async for loop,所以 while loop + Iterator<Item = T> 来模拟之。
while let Some(stream) = incoming.next().await {
// TODO
}
Ok(())
}
fn main() {
let fut = accept_loop("127.0.0.1:8080");
task::block_on(fut); // 异步函数外的人工启动 Future
}
1
共 1 条评论, 1 页
评论区
写评论impl Feutres