在Rust中,我发现除非等待,否则在运行时不会调用异步任务或函数(甚至可以说是未来的任务)。在其他语言(如C#或NodeJS )中,可以定义async任务并并发运行它们,因为async任务的目的是提供非阻塞IO。例如:
public Task Run();
public Task ListenToMusic();
public async Task RunAndListenToMusic() {
Task run = Run(); // the task is already running
Task listenToMusic = ListenToMusic(); // the task is already running
await Task.WhenAll(run, listenToMusic);
}我使用for循环在Rust中测试了这个机制,这个循环实际上打印出了序列号,并发现它们总是按照顺序执行,这意味着第二个任务是在第一个任务之后运行的。
对于像我这样来自dotnet或Java世界的人来说,这是一种奇怪的行为。实际上是怎么回事,我搜索了,但我需要一个人来解释这一点,更多的细节,更简单。
发布于 2021-12-15 08:11:33
下面是一些与您的示例等效的锈蚀代码:
use tokio; // 1.14.0
async fn task1() {
for i in 0..10 {
println!("Task 1: {}", i);
}
}
async fn task2() {
for i in 0..10 {
println!("Task 2: {}", i);
}
}
#[tokio::main]
async fn main() {
let t1 = task1();
let t2 = task2();
tokio::join!(t1, t2);
}如果运行此代码,您将注意到它在执行task1之前会执行所有的task2。这是预期的,因为执行是单线程的,所以只要task1不尝试阻塞操作,它就会运行。但是,如果我们添加阻塞操作(这里我使用了sleep,但I/O操作也是如此):
use std::time::Duration;
use tokio; // 1.14.0
async fn task1() {
for i in 0..10 {
println!("Task 1: {}", i);
tokio::time::sleep (Duration::from_millis (1)).await;
}
}
async fn task2() {
for i in 0..10 {
println!("Task 2: {}", i);
tokio::time::sleep (Duration::from_millis (1)).await;
}
}
#[tokio::main]
async fn main() {
let t1 = task1();
let t2 = task2();
tokio::join!(t1, t2);
}现在我们看到操作是交织在一起的:当一个任务阻塞时,其他任务就有机会运行,这就是异步编程的全部要点。
https://stackoverflow.com/questions/70357544
复制相似问题