"tokio::spawn(my_future).await和仅使用my_future.await的区别是什么?"

34

假设有一个异步函数及其对应的 Future:

async fn foo() -> Result<i32, &'static str> {
    // ...
}

let my_future = foo();

使用只有 .await 和使用 tokio::spawn().await 有什么区别?

// like this...
let result1 = my_future.await;

// ... and like this
let result2 = tokio::spawn(my_future).await;

1
my_future.await需要在其后紧跟的任何代码运行之前完成。生成新任务将继续当前任务,同时在新任务中运行未来。 - Peter Hall
1个回答

41

通常情况下,不需要等待一个新创建的任务(至少不是立即等待)。更常见的做法是直接编写:

tokio::spawn(my_future);

如果不加上.await,那么任务将在后台运行,而当前任务继续执行。立即调用.await会阻塞当前任务。spawn(task).awaittask.await实际上没有任何区别。这类似于创建一个线程并立即加入它,同样是毫无意义的。

与裸的future不同,生成的任务不需要像那样等待。等待它们是可选的。那么什么情况下需要等待呢?如果您希望阻塞当前任务直到生成的任务完成,则需要等待。

let task = tokio::spawn(my_future);

// Do something else.
do_other_work();

// Now wait for the task to complete, if it hasn't already.
task.await;

如果你需要结果,但是在开始任务和收集结果之间需要做一些工作。

let task = tokio::spawn(my_future);

// Do something else.
do_other_work();

// Get the result.
let result = task.await;

1
我想我明白了。我以为两个future(我的future和tokio::spawn返回的future)都不会执行任何操作,直到被awaited。我认为每个future都是懒加载的。那么我想我错了,你的解释很有道理!谢谢。 - hbobenicio
4
@hbobenicio 今天我也有同样的问题。看起来 tokio::spawn 就像 thread::spawn,当你生成时,它会在后台运行。 - ccQpein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接