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(){}
,这使我没有使用闭包。非常感谢你!