首页 > 解决方案 > 是否可以将 async_trait 与动态调度一起使用

问题描述

我正在尝试创建一个使用对 Iterator 的 dyn 引用的 async_trait。

这是我的代码示例:

#[async_trait::async_trait]
trait StringPrinter { 
    async fn print(a: &mut dyn Iterator<Item = String>); 
}

struct MyStringPrinter{} 

#[async_trait::async_trait]
impl StringPrinter for MyStringPrinter { 
    async fn print(a: &mut dyn Iterator<Item = String>){
       a.for_each(|x| println!("{}", x));     
       tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; 
    }
}

但是编译器抱怨:future created by async block is not 'Send'

另一方面 - async 函数的简单版本运行良好:

async fn print_iterator(a: &mut dyn Iterator<Item = String>) { 
    a.for_each(|x| println!("{}", x));     
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; 
}

知道有什么不同吗?或任何解决方法的想法?

标签: rusttraitsrust-tokio

解决方案


是的,这是可能的,毕竟#[async_trait]proc-macro 重写了方法以使用盒装的未来。这在crate的文档中进行了解释:

异步 fns 被转换为返回Pin<Box<dyn Future + Send + 'async>>并委托给私有async独立函数的方法。

Send但是当且仅当它的所有成员都实现时,生成的未来才会是Send。然而你的迭代器没有:

&mut dyn Iterator<Item = String>

只需将其更改为:

&mut (dyn Iterator<Item = String> + Send)

推荐阅读