如何解决在 run_interval 中运行异步函数并返回结果
我需要在 actix::prelude::AsyncContext::run_interval
中运行一个异步函数,但我还需要传入一个结构体成员并返回结果(不是未来)。这是 this question here 的一个稍微复杂的版本。从下面的评论部分可以看出,我尝试了几种方法,但由于某种原因,所有方法都失败了。
我查看了一些相关资源,包括 the AsyncContext trait 和这些 StackOverflow 问题:3、4。
这是我的示例代码(actix
中需要 Cargo.toml
crate):
use std::time::Duration;
use actix::{Actor,Arbiter,AsyncContext,Context,System};
struct MyActor {
id: i32
}
impl MyActor {
fn new(id: i32) -> Self {
Self {
id: id,}
}
fn heartbeat(&self,ctx: &mut <Self as Actor>::Context) {
ctx.run_interval(Duration::from_secs(1),|act,ctx| {
//lifetime issue
//let res = 0;
//Arbiter::spawn(async {
// res = two(act.id).await;
//});
//future must return `()`
//let res = Arbiter::spawn(two(act.id));
//async closures unstable
//let res = Arbiter::current().exec(async || {
// two(act.id).await
//});
});
}
}
impl Actor for MyActor {
type Context = Context<Self>;
fn started(&mut self,ctx: &mut Self::Context) {
self.heartbeat(ctx);
}
}
// assume functions `one` and `two` live in another module
async fn one(id: i32) -> i32 {
// assume something is done with id here
let x = id;
1
}
async fn two(id: i32) -> i32 {
let x = id;
// assume this may call other async functions
one(x).await;
2
}
fn main() {
let mut system = System::new("test");
system.block_on(async { MyActor::new(10).start() });
system.run();
}
Rust 版本:
$ rustc --version
rustc 1.50.0 (cb75ad5db 2021-02-10)
解决方法
使用 Arbiter::spawn 会起作用,但问题在于从传递给 Arbiter::spawn 的异步块内部访问的数据。由于您是从 async 块内部访问 act
,因此该引用必须比调用 Arbiter::spawn 的闭包存活时间更长。事实上,in 必须有一个 'static 的生命周期,因为异步块产生的未来可能会持续到程序结束。
在这种特定情况下解决此问题的一种方法是移动它:
ctx.run_interval(Duration::from_secs(1),|act,ctx| {
let id = act.id;
Arbiter::spawn(async move {
two(id).await;
});
});
由于我们使用了 async move
,因此 id 变量将被移动到未来,因此在未来运行时将可用。通过首先将其分配给 id
,我们实际上是在复制数据,并且将移动的是副本 (id
)。
但这可能不是您想要的,如果您想获得一个更通用的解决方案,您可以在其中访问异步函数中的对象。在这种情况下,它会变得有点棘手,如果可能,您可能需要考虑不使用异步函数。如果必须,可能有一个单独的对象包含您需要的数据,用 std::rc::Rc
包围,然后可以将其移动到异步块中,而无需复制基础数据。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。