下面的代码描述了一个容器,用于使用HashMap准备好的异步调用:
use std::{
collections::HashMap,
any::Any,
marker::Send
};
use futures::future::{Future, BoxFuture};
// ===================================
pub type AnyType = Box<dyn Any + Send>;
// ===================================
trait AsyncFn {
fn call(&self, arg: AnyType) -> BoxFuture<'static, ()>;
}
impl<T, F> AsyncFn for T
where
T: Fn(AnyType) -> F,
F: Future<Output = ()> + 'static + Send,
{
fn call(&self, arg: AnyType) -> BoxFuture<'static, ()> {
Box::pin(self(arg))
}
}
async fn async_test(data: AnyType) -> () {
let d: Box<String> = data.downcast().unwrap();
println!("String data = {d:?}");
}
#[async_std::main]
async fn main() {
let mut callables: HashMap<String, Box<dyn AsyncFn>> = HashMap::new();
callables.insert(
"test_func".to_string(),
Box::new(async_test)
);
let awaitable = callables.get("test_func").unwrap();
awaitable.call(Box::new("test string argument1".to_string())).await;
}
我所面临的任务是为将来的调用做准备,不仅要准备一个异步函数,还要准备一个额外的相关参数,我试着这样做:
use std::{any::Any, collections::HashMap};
use futures::future::{Future, BoxFuture};
pub type AnyType = Box<dyn Any + Send + Sync>;
pub type AnyBindType = Option<AnyType>;
// ===================================
trait AsyncBindFn {
fn call(&self, arg: AnyBindType) -> BoxFuture<'static, ()>;
}
impl<T, F> AsyncBindFn for T
where
T: Fn(AnyBindType) -> F,
F: Future<Output = ()> + 'static + Send + Sync,
{
fn call(&self, arg: AnyBindType) -> BoxFuture<'static, ()> {
Box::pin(self(arg))
}
}
async fn async_test2(data: AnyBindType) -> () {
if let Some(ref d) = data {
let d = d.downcast_ref::<String>();
println!("String data = {d:?}");
}
}
#[tokio::main]
async fn main() {
let mut bind_callables: HashMap<String, (Box<dyn AsyncBindFn>, AnyBindType)> = HashMap::new();
bind_callables.insert(
"bind_test_func".to_string(),
(
Box::new(async_test2),
Some(Box::new("test bind string argument1".to_string())),
),
);
let bind_awaitable_data = bind_callables.get("bind_test_func").unwrap();
let (bind_awaitable, bind_arg) = bind_awaitable_data;
// if let Some(ref d) = bind_arg {
// let d = d.downcast_ref::<String>();
// println!("String data = {d:?}");
// }
bind_awaitable.call(bind_arg).await; // ! ERROR
// ^^^^^^^^ - mismatched type
}
在数据被传输到HashMap
之后,获取原始数据的唯一方法是在其上执行remove()
,但我需要能够重用它。
在最后一个例子中,if let
的最后一个注解块成功地打印了这个数据,但是由于它是一个引用,我不能发送它在相应的函数中做同样的事情,因为它是一个类型不匹配。
因此,签名的描述应该相应地改变,以便函数引用一个可选参数,但是当我接收到它时,我将引用一个可选数据的引用,等等......
如何克服这种情况?
1条答案
按热度按时间6ojccjat1#
impl Future
应在返回值定义中显式使用: