< 返回版块

缘罪 发表于 2024-10-22 17:35

Tags:异步,tokio,错误

trait MethodTrait {
    async fn async_method(&self);
}

#[derive(Clone)]
struct MyStruct {}
impl MethodTrait for MyStruct {
    async fn async_method(&self) {
        todo!() // 占位
    }
}

struct Demo<T>
where
    T: MethodTrait + Clone + Sync + Send + 'static,
{
    parser: T,
}

impl<T> Demo<T>
where
    T: MethodTrait + Clone + Sync + Send + 'static,
{
    fn new(parser: T) -> Self {
        Demo { parser }
    }
    async fn execute(&self) {
        let parser = self.parser.clone();
        tokio::spawn(async move {
            // parser.async_method().await; // 这里会报错
            test_fn().await; // 这里正常执行
        });
    }
}

#[tokio::main]
async fn main() {
    let my_struct = MyStruct {};
    let demo = Demo::new(my_struct);
    demo.execute().await;
}

async fn test_fn() {
    println!("hello world")
}

错误信息: the trait Send is not implemented for impl Future<Output = ()>, which is required by : Send

这里没搞懂为什么不能直接写async方法,要写同步方法然后自己手动约束返回值的send。

评论区

写评论
TinusgragLin 2024-10-22 18:40

我没搞懂这块为啥需要约束Send

哦,我知道了,你的疑惑是不是为啥 tokio::spawn 需要一个 Send 的 Future?

如果我理解没错的话,这是因为 tokio 的任务调度系统默认开了任务窃取,如果某个 worker 线程闲得发慌可以把其他 worker 线程任务队列中的 Future 给这个线程,所以需要 Future 的 ownership 可以在不同线程间转移,所以需要 Send 约束,字节有一个(为负载均衡任务设计的)monoio 异步运行时就没有这个要求了。

bestgopher 2024-10-22 18:31

学到了 https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=41b5bb02843224f46c7eb5fdedfe44e5

--
👇
TinusgragLin: 如果我记得没错的话,目前 trait 中的 async 方法返回的 Future 默认是没有 Send 约束的,不过现在 nightly 有了 return type notation 之后,就可以加一个这样的约束了:

T::async_method(..): Send
Bai-Jinlin 2024-10-22 18:25

trait MethodTrait {
    async fn async_method(&self);
}

改成

trait MethodTrait {
    fn async_method(&self) -> impl std::future::Future<Output = ()> + Send;
}

参考 https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html#async-fn-in-public-traits

TinusgragLin 2024-10-22 18:22

大概是因为现在 trait 中的 async 方法实际上跟这样写

fn async_method(&self) -> impl Future;

差不多,返回值是一个“opaque type”(实际类型“隐藏”的类型),对于类型系统来说,这就是“某一个”实现了的 Future trait 的类型,而不会考虑它的实际类型,所以类型检查的时候会很保守。

之前官方的博客有一篇相关的文章,你可以参考一下。

作者 缘罪 2024-10-22 18:19

我没搞懂这块为啥需要约束Send

--
👇
TinusgragLin: 如果我记得没错的话,目前 trait 中的 async 方法返回的 Future 默认是没有 Send 约束的,不过现在 nightly 有了 return type notation 之后,就可以加一个这样的约束了:

T::async_method(..): Send
TinusgragLin 2024-10-22 18:06

如果我记得没错的话,目前 trait 中的 async 方法返回的 Future 默认是没有 Send 约束的,不过现在 nightly 有了 return type notation 之后,就可以加一个这样的约束了:

T::async_method(..): Send
1 共 6 条评论, 1 页