我对 Rust 很陌生,所以也许我错过了一些明显的东西。
此代码工作正常:
pub fn say_hello() {
let fut = tokio::io::write_all(tokio::io::stdout, "Hello, world!").then(|_| {});
tokio::run(fut);
}
而以下代码编译失败:
pub fn say_hello(w: Box<dyn tokio::io::AsyncWrite>) {
let fut = tokio::io::write_all(w, "Hello, world!").then(|_| {});
tokio::run(fut);
}
编译器错误为:
error[E0277]: `dyn tokio_io::async_write::AsyncWrite` cannot be sent between threads safely
有没有办法完成我想要的(实际上是动态调度,而不仅仅是使函数通用)。
TL;DRtokio::run
expects
未来,在Send
和'static
生命周期内实施。
如果向参数添加所需的限制,它将与Stdout
相同:
pub fn say_hello(w: Box<dyn tokio::io::AsyncWrite + Send + 'static>) {
let fut = tokio::io::write_all(w, "Hello, world!").then(|_| Ok(()));
tokio::run(fut);
}
注意:Stdout
工作是因为 Stdout 实现已经包含Send
,并且它是封闭范围的自有数据。
但是 Rust 如何能够知道write_all
创建的Future
是否Send
?
使用AsyncWrite
的实现调用write_all
是可以的,因为tokio::io::write_all期望实现AsyncWrite
。但是tokio::run期望一个拥有或'static
Future
实现Send
您正在尝试运行WriteAll
未来,但请检查此Send
WriteAll
实现,它仅在T
和A
实现Send
时实现Send
。在您的情况下T
是您的 buf 类型,它是&'static str
,它实现了 Send,A
是AsyncWrite
的实现。
在这个定义中,没有声明w
是Send
(或者它有一个'static
/拥有的生命周期):
pub fn say_hello(w: Box<dyn tokio::io::AsyncWrite>)
这就是为什么东京跑不接受WriteAll
未来。