我得到了这段无法编译的代码。
[dependencies] tokio = {version = "1.37.0", features = ["full"]}
use std::error::Error;
async fn external_function() -> Result<i32, Box<dyn Error>>{
println!("This is an external function!");
Ok(1)
}
async fn my_function(something: i32) {
println!("This is my function {something}");
}
#[tokio::main]
async fn main() {
println!("Hello, world!");
let runtime = tokio::runtime::Runtime::new().unwrap();
runtime.spawn(async move {
let v = external_function().await;
if let Ok(x) = v {
my_function(x).await;
}
});
}
问题是我从一个箱子中得到了一个异步函数,它返回一个
Result<T, Box<dyn Error>>
我想处理这些结果,如果是 Ok()
,请使用结果值调用我的函数。
但是我得到了这个编译器错误:
error: future cannot be sent between threads safely
鉴于我无法修改
external_function()
,实现此操作没有错误的最佳实践是什么?
一种解决方案是使
my_function()
成为非异步的,但如果我也希望它是异步的怎么办?
问题是我从一个箱子中得到了一个异步函数,它返回一个
Result<T, Box<dyn Error>>
通过返回
Box<dyn Error>
,该箱子给了你一个错误类型,根本不能保证线程安全。除了在单线程代码中之外,您无法传递此Box<dyn Error>
。
由于该函数也是
async
,这意味着它的 Future
也必须在单线程环境中运行,例如 LocalSet
或简单地从新线程调用 Handle::block_on()
。
一旦你成功运行了 future,为了通过你自己的异步函数传递错误,你只能利用
Error
特征: 提供的功能
Display
特征将其转换为字符串:调用 error.to_string()
。Debug
特征将其转换为字符串:format!("{error:?}")
。dyn
背后具体的错误类型,并且该类型 is Send
,那么您可以使用 Error::downcast()
来获取该类型而不是 dyn Error
— 那么缺少 + Send
上的dyn Error
不再重要了。