use std::future::Future;
use std::task::{Context, Poll};
async fn bar() {
// Force to yield back to the caller.
let mut yielded = false;
std::future::poll_fn(move |_| {
if !yielded {
yielded = true;
Poll::Pending
} else {
Poll::Ready(())
}
})
.await;
}
async fn foo() {
println!("before");
bar().await;
println!("after");
}
fn main() {
let waker = futures::task::noop_waker();
let mut context = Context::from_waker(&waker);
let mut future = Box::pin(foo());
// First, poll the future once.
assert_eq!(future.as_mut().poll(&mut context), Poll::Pending);
// Now the future is paused at the `.await` inside `bar()`. Poll it again so it completes.
assert_eq!(future.as_mut().poll(&mut context), Poll::Ready(()));
}
2条答案
按热度按时间8yoxcaq71#
它还没有结束,只是暂停了。当未来再次被轮询时,它将继续下去。
下面是一个例子:
Playground.
通常,
Waker
注册到future,以便在某个事件发生时再次轮询,然后调度程序在事件发生时轮询它。例如,如果您在tokio中执行I/O,则分配给您的future的waker将注册它,以便在I/O就绪时再次轮询它。xtupzzrd2#
你可以想到时雄(和其他异步运行时)作为调度程序,异步函数作为要完成的任务。在此上下文中,“yeild”表示正在运行的任务可以决定暂停执行,以便将控制权交还给调度程序,这样该线程就可以用于处理另一个任务(如果有其它任务排队)。如果没有其它任务可用,那么调度程序可能决定继续前一个任务。2任务并没有结束。3这更像是我们保存了自己在任务中的位置,以便以后可以返回到它。
所以当你调用一个异步函数的时候,你实际上是给调度器一个新任务,然后当你使用
.await
的时候,你告诉调度器你想等待那个任务的结果,这使得yield成为一个理想的选择,因为在另一个任务完成之前我们什么也做不了,我们想释放资源,这样在等待的时候其他任务就可以被处理了。