我有这样一个简单的代码来模拟异步代码在阻塞操作中的工作方式。
我期待所有这些“你好”打印将显示在1000毫秒后。
但是这段代码的工作方式就像一个普通的阻塞代码,每个hello_wait调用等待1000 and,并在1000 and之后打印另一个Hello。
如何使它同时运行?
use std::{time::Duration};
use async_std::task;
async fn hello_wait(){
task::sleep(Duration::from_millis(1000)).await;
println!("Hello");
}
#[async_std::main]
async fn main() {
hello_wait().await;
hello_wait().await;
hello_wait().await;
hello_wait().await;
hello_wait().await;
}这就是正在发生的事情:
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello这就是我想要的:
// -- Wait 1000ms --
Hello
Hello
Hello
Hello
Hello发布于 2021-11-16 12:13:53
如何使它同时运行?
你可以:
您的期望可能来自Javascript或C#异步,其中“基本”是一个任务。任务是“活动的”,一旦您创建它们,它们就可以被调度并同时执行它们的任务。
但铁锈的核心更像是一种协同机制,所以它是惰性的(/被动的):创建一个人并不能真正做任何事情,未来必须对进展进行调查,await将在恢复之前反复进行投票,直到完成为止。所以当你await某件东西时,它完全运行,没有机会在这一点上交织。
因此,同时经营期货需要两件事之一:
spawn所做的join_all或tokio::join这样的构造。请注意,组合期货不允许并行性,因为期货是“兄弟姐妹”--它们只能被连续地进行民意测验(因此实际上是做事情),只是这种轮询(以及由此产生的进展)被交织在一起。
生成任务确实允许并行性(如果运行时是多重的,并且机器有多个内核--尽管后者现在已经相当通用),但在生命周期和内存管理方面有其自身的局限性,而且要花费更多。
以下是各种选项的游乐场演示。它使用tokio,因为显然操场上没有async_std,而且我不确定它是否能够启用“不稳定”特性,但除此之外,使用tokio::join (异步std的Future::join一次只能加入2个期货),所以您必须链接调用),它在async_std中的工作方式应该大致相同。
发布于 2021-11-16 12:20:20
我可以用futures的join_all这样做
use std::time::Duration;
use async_std::task;
use futures::future;
async fn hello_wait(){
task::sleep(Duration::from_millis(1000)).await;
println!("Hello");
}
#[async_std::main]
async fn main() {
let mut asyncfuncs = vec![];
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
future::join_all(asyncfuncs.into_iter()).await;
}https://stackoverflow.com/questions/69988593
复制相似问题