asynchronous - Rust 异步方法回调/关闭
问题描述
我有一个情况,有一个服务管理器(结构 B)持有一个数字服务(结构 A),需要调用服务管理器中的一个方法(例如 self.test with self in B),所有工作都深深嵌套在 async tokio代码。虽然我能够将服务管理器的克隆“附加”到每个服务以便能够调用其方法,但我希望只允许访问服务管理器中的特定 async(!) 方法,即我只想例如,将服务管理器的一种方法附加到服务。(对于那些对真实系统感兴趣的人,一些服务调用其他服务中的方法并通过服务管理器中的调用来获取它们,我知道有频道、发布/订阅等内容,但我对这个特定的解决方案感兴趣设置,因为我经常遇到它... ) 不幸的是,我无法找到正确的方法来设置这样的回调。下面是整个设置的一个非常简化的版本:
#![feature(async_closure)]
use std::sync::Arc;
type AsyncClosure = ???;
struct A {
value: String,
callback_to_fn_in_B: Option<AsyncClosure>,
}
impl A {
fn set_callback_to_method_in_B(&mut self, f: Option<AsyncClosure>) {
self.callback_to_fn_in_B = f;
}
}
struct B {
b: String,
a: Arc<A>,
}
impl B {
async fn test(&self, arg0: &str) -> String {
// to simulate some async work:
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
format!("b + arg0 = {}{}", self.b, arg0)
}
fn attach_self_callback_to_A(&self) {
let callback = async move |arg: &str| {
self.test(arg).await
};
self.a.set_callback_to_method_in_B(Some(callback));
}
}
#[tokio::main]
async fn main() {
tokio::spawn(async move {
let a = Arc::new(A { value: "value".to_owned(), callback_to_fn_in_B: None });
let b = B { b: "hello".to_owned(), a: a.clone() };
b.attach_self_callback_to_A();
match a.callback_to_fn_in_B.as_ref() {
Some(f) => println!("{:?}", f(" world")),
None => {},
}
});
}
我把 tokio 等留在了那里,以表明整个系统应该跨线程工作,即某些部分可能需要 + 发送 + 同步。如何定义 AsyncClosure 类型?是否可以避免关闭(我会用它来捕获主体结构 B 的自我)?任何帮助是极大的赞赏!
基于下面的第一个答案,我转到以下版本:
#![feature(async_closure)]
#![allow(unused_imports)]
use std::sync::Arc;
use std::error::Error;
use futures::future::Future;
use std::pin::Pin;
type AsyncClosure = Box<dyn for<'a> FnMut(&'a str) -> Pin<Box<dyn Future<Output = String> + 'a + Send + Sync>> + Send + Sync>;
struct A
{
value: String,
callback_to_fn_in_B: Option<AsyncClosure>,
}
impl A
{
fn set_callback_to_method_in_B(&mut self, f: Option<AsyncClosure>) {
self.callback_to_fn_in_B = f;
}
}
struct B
{
b: String,
a: Arc<A>,
}
impl B
{
async fn test(&self, arg0: &str) -> String {
// to simulate some async work:
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
format!("b + arg0 = {}{}", self.b, arg0)
}
async fn attach_self_callback_to_A(&self) {
let this = self.clone();
let callback: AsyncClosure = Box::new(|arg| { Box::pin(async move { this.test(arg).await })});
self.a.set_callback_to_method_in_B(Some(callback));
}
}
#[tokio::main]
async fn main() {
tokio::spawn(async move {
let a = Arc::new(A { value: "value".to_owned(), callback_to_fn_in_B: None });
let b = B { b: "hello".to_owned(), a: a.clone() };
b.attach_self_callback_to_A();
match a.callback_to_fn_in_B.as_ref() {
Some(f) => {
println!("{:?}", f("test").await)
},
None => {},
}
});
}
但是,现在编译器抱怨说,由于 fn attach_self_callback_to A 中 &self 的要求相互冲突,它无法推断出适当的生命周期。错误消息很长,而且大部分都是重复的,没有给我任何真正的帮助。有人知道如何解决这个问题吗?
解决方案
推荐阅读
- html - 具有自动适应功能的网格
- ruby-on-rails - 使用茧宝石时看不到部分
- python - Python函数从未见过
- javascript - 如何导出 javascript 类以在测试单元中使用?
- amazon-dynamodb - 如何通过解析器将 cognito userEmails 添加到 DynamoDB 表?
- java - Heroku 构建在 gradle 任务“nodeSetup”期间失败,错误“无法遵循符号链接”
- unity3d - 计算轨道路径中给定可变斜边的方向向量
- c# - 用于非托管 API 调用的具有固定大小数组的 Marshal 结构
- python - 在训练和测试时间 pytorch 上以不同方式管理内存
- python - 如何使用 sorted() 函数在 Python 3 中对 CSV 文件中的数据进行排序?