Asynchronous 从闭包调用异步函数
我想在迭代器中使用的闭包中等待Asynchronous 从闭包调用异步函数,asynchronous,rust,async-await,future,Asynchronous,Rust,Async Await,Future,我想在迭代器中使用的闭包中等待异步函数。需要闭包的函数在结构实现中调用。我不知道该怎么做 此代码模拟了我正在尝试执行的操作: struct MyType{} impl MyType{ 异步fn foo(&self){ println!(“foo”); (0..2).对于每个(v){ 自我酒吧(五)等待; }); } 异步fn条(&self,v:usize){ println!(“条:{}”,v); } } #[tokio::main] 异步fn main(){ 设mt=MyType{}; 福山(
异步函数。需要闭包的函数在结构实现中调用。我不知道该怎么做
此代码模拟了我正在尝试执行的操作:
struct MyType{}
impl MyType{
异步fn foo(&self){
println!(“foo”);
(0..2).对于每个(v){
自我酒吧(五)等待;
});
}
异步fn条(&self,v:usize){
println!(“条:{}”,v);
}
}
#[tokio::main]
异步fn main(){
设mt=MyType{};
福山()等待;
}
显然,这将不起作用,因为闭包不是async
,给了我:
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> src/main.rs:8:13
|
7 | (0..2).for_each(|v| {
| --- this is not `async`
8 | self.bar(v).await;
| ^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
在寻找如何从非async
函数调用async
函数的答案后,我得出以下结论:
东京:产卵(异步移动){
自我酒吧(五)等待;
});
但现在我要讨论的是终身问题:
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:4:18
|
4 | async fn foo(&self) {
| ^^^^^
| |
| this data with an anonymous lifetime `'_`...
| ...is captured here...
...
8 | tokio::spawn(async move {
| ------------ ...and is required to live as long as `'static` here
这也不奇怪,因为据我所知,Rust编译器无法知道线程的寿命。考虑到这一点,使用tokio::spawn
生成的线程可能比类型MyType
更长寿
我想到的第一个修复方法是将bar
作为一个关联函数,复制闭包中需要的所有内容,并将其作为值传递给bar
,然后使用MyType::bar(从自身复制)
调用它,但这越来越糟糕,因为复制太多了。它也感觉像是一个不知道生命周期如何工作的变通方法
相反,我尝试在
上使用futures::executor::block_,它适用于像本文中这样的简单任务:
(0..2).对于每个(| v|){
期货:执行人:block_on(self.bar(v));
});
但在我的现实生活中,我使用了第三方图书馆1,该图书馆也使用了东京
,但当我把它放在这个例子中时,事情就不再起作用了。阅读文档后,我意识到#[tokio::main]
是一个宏,它最终会将所有内容包装在块中,因此通过这样做,就会在上嵌套块。这可能就是为什么在bar
中调用的async
方法之一在没有任何错误或日志记录的情况下停止工作的原因(在没有block_on
的情况下工作,因此不应该与代码有任何关系)。我联系了作者,他们说我可以为每个人使用(|I | async move{…})
,这让我更加困惑
(0..2).对于每个(| v |异步移动){
自我酒吧(五)等待;
});
将导致编译错误
expected `()`, found opaque type`
我认为这是有道理的,因为我现在返回的是一个未来,而不是()
。我天真的做法是尝试用这样的方式等待未来:
(0..2).对于每个(| v|){
异步移动{
自我酒吧(五)等待;
}
.等待
});
但这让我回到了第一步,导致了下面的编译错误,我认为这也是有意义的,因为我现在又回到了在闭包中使用wait
,即sync
only allowed inside `async` functions and blocks` since the
这一发现也让我很难利用找到的和找到的答案
在所有这些cargo cult编程之后的问题基本上是,有可能吗?如果有,我如何在迭代器中从闭包调用我的async
函数?如果这是不可能的,那么它的惯用实现会是什么样子
1迭代器::for_每个
都需要一个同步clsure,因此您不能在其中使用。等待
(至少不能直接等待),也不能从中返回未来
一种解决方案是只对
循环使用,而不是
0..2中v的{
自我酒吧(五)等待;
}
更通用的方法是使用迭代器而不是迭代器,因为迭代器是异步等效的(流上的等效方法通常也是异步的)。这不仅适用于每个
的,而且适用于大多数其他迭代器方法:
use futures::prelude::*;
未来::流::iter(0..2)
.for|u each(| c |异步移动{
自我酒吧(五)等待;
})
.等待;
非常感谢您!实际的迭代器不是每个的,而是。这意味着我不能真正更改为for
循环,也不能使用futures::stream::iter
。有鉴于此,除了使用tokio::spawn
并从self
复制我需要的所有数据之外,你还有其他解决方案吗?我现在意识到,除了尝试每个之外,可能还有其他方法可以使用?你的回答让我读到了关于流的书,意识到我在用流工作。我更改了stream.try_for_each(|m |{})
为,而let Some(x)=stream.try_next().wait.unwrap(){}
,这使我没有使用闭包。非常感谢你!