异步任务中止时会发生什么?
What happens to an async task when it is aborted?
Rust 有 async
可以绑定到 Abortable
期货的方法。文档说,中止时:
the future will complete immediately without making any further progress.
未来绑定的任务所拥有的变量是否会被丢弃?如果那些变量实现 drop
,会调用 drop
吗?如果 future 又衍生出其他 futures,会不会都链式中止?
例如:In the following snippet,我没有看到析构函数发生在被中止的任务中,但我不知道它是没有被调用还是发生在一个单独的线程,其中 print 未显示。
use futures::executor::block_on;
use futures::future::{AbortHandle, Abortable};
struct S {
i: i32,
}
impl Drop for S {
fn drop(&mut self) {
println!("dropping S");
}
}
async fn f() -> i32 {
let s = S { i: 42 };
std::thread::sleep(std::time::Duration::from_secs(2));
s.i
}
fn main() {
println!("first test...");
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let _ = Abortable::new(f(), abort_registration);
abort_handle.abort();
std::thread::sleep(std::time::Duration::from_secs(1));
println!("second test...");
let (_, abort_registration) = AbortHandle::new_pair();
let task = Abortable::new(f(), abort_registration);
block_on(task).unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
}
是的,已创建 的值将被删除。
在您的第一个示例中,f
返回的未来从未开始,因此从未创建 S
。这意味着它不能被删除。
在第二个示例中,值被删除。
如果你 运行 未来 和 中止它,这将更加明显。在这里,我产生了两个并发的期货:
- 创建一个
S
并等待 200 毫秒
- 等待 100 毫秒并中止未来 #1
use futures::future::{self, AbortHandle, Abortable};
use std::time::Duration;
use tokio::time;
struct S {
i: i32,
}
impl S {
fn new(i: i32) -> Self {
println!("Creating S {}", i);
S { i }
}
}
impl Drop for S {
fn drop(&mut self) {
println!("Dropping S {}", self.i);
}
}
#[tokio::main]
async fn main() {
let create_s = async {
let s = S::new(42);
time::delay_for(Duration::from_millis(200)).await;
println!("Creating {} done", s.i);
};
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let create_s = Abortable::new(create_s, abort_registration);
let abort_s = async move {
time::delay_for(Duration::from_millis(100)).await;
abort_handle.abort();
};
let c = tokio::spawn(create_s);
let a = tokio::spawn(abort_s);
let (c, a) = future::join(c, a).await;
println!("{:?}, {:?}", c, a);
}
Creating S 42
Dropping S 42
Ok(Err(Aborted)), Ok(())
请注意,我已切换到 Tokio 以便能够使用 time::delay_for
,因为您永远不应该在异步函数中使用阻塞操作。
另请参阅:
If the future has spawned other futures, will all of them be aborted in a chain?
不,当你 spawn
一个未来时,它与它产生的地方断开连接。
另请参阅:
Rust 有 async
可以绑定到 Abortable
期货的方法。文档说,中止时:
the future will complete immediately without making any further progress.
未来绑定的任务所拥有的变量是否会被丢弃?如果那些变量实现 drop
,会调用 drop
吗?如果 future 又衍生出其他 futures,会不会都链式中止?
例如:In the following snippet,我没有看到析构函数发生在被中止的任务中,但我不知道它是没有被调用还是发生在一个单独的线程,其中 print 未显示。
use futures::executor::block_on;
use futures::future::{AbortHandle, Abortable};
struct S {
i: i32,
}
impl Drop for S {
fn drop(&mut self) {
println!("dropping S");
}
}
async fn f() -> i32 {
let s = S { i: 42 };
std::thread::sleep(std::time::Duration::from_secs(2));
s.i
}
fn main() {
println!("first test...");
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let _ = Abortable::new(f(), abort_registration);
abort_handle.abort();
std::thread::sleep(std::time::Duration::from_secs(1));
println!("second test...");
let (_, abort_registration) = AbortHandle::new_pair();
let task = Abortable::new(f(), abort_registration);
block_on(task).unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
}
是的,已创建 的值将被删除。
在您的第一个示例中,f
返回的未来从未开始,因此从未创建 S
。这意味着它不能被删除。
在第二个示例中,值被删除。
如果你 运行 未来 和 中止它,这将更加明显。在这里,我产生了两个并发的期货:
- 创建一个
S
并等待 200 毫秒 - 等待 100 毫秒并中止未来 #1
use futures::future::{self, AbortHandle, Abortable};
use std::time::Duration;
use tokio::time;
struct S {
i: i32,
}
impl S {
fn new(i: i32) -> Self {
println!("Creating S {}", i);
S { i }
}
}
impl Drop for S {
fn drop(&mut self) {
println!("Dropping S {}", self.i);
}
}
#[tokio::main]
async fn main() {
let create_s = async {
let s = S::new(42);
time::delay_for(Duration::from_millis(200)).await;
println!("Creating {} done", s.i);
};
let (abort_handle, abort_registration) = AbortHandle::new_pair();
let create_s = Abortable::new(create_s, abort_registration);
let abort_s = async move {
time::delay_for(Duration::from_millis(100)).await;
abort_handle.abort();
};
let c = tokio::spawn(create_s);
let a = tokio::spawn(abort_s);
let (c, a) = future::join(c, a).await;
println!("{:?}, {:?}", c, a);
}
Creating S 42
Dropping S 42
Ok(Err(Aborted)), Ok(())
请注意,我已切换到 Tokio 以便能够使用 time::delay_for
,因为您永远不应该在异步函数中使用阻塞操作。
另请参阅:
If the future has spawned other futures, will all of them be aborted in a chain?
不,当你 spawn
一个未来时,它与它产生的地方断开连接。
另请参阅: