我想在 Future::poll() 中调用异步函数,但 poll() 不是异步函数,所以我必须轮询异步 fn,但出现错误:
error[E0599]: no method named `poll` found for opaque type `impl Future` in the current scope
--> src\lib.rs:18:22
|
18 | let a = fut1.poll(cx);
| ^^^^ method not found in `impl Future`
Run Code Online (Sandbox Code Playgroud)
我尝试 Pin::new(async fn()).poll(),得到另一个错误:
error[E0277]: `from_generator::GenFuture<[static generator@src\lib.rs:33:23: 36:2 {ResumeTy, u64, Duration, impl Future, ()}]>` cannot be unpinned
--> src\lib.rs:22:23
|
22 | let pinfut1 = Pin::new(&mut fut1);
| ^^^^^^^^ within `impl Future`, the trait `Unpin` is not implemented for `from_generator::GenFuture<[static generator@src\lib.rs:33:23: 36:2 {ResumeTy, u64, Duration, impl Future, ()}]>`
...
33 | async fn fn1() -> i32 {
| --- within this `impl Future`
Run Code Online (Sandbox Code Playgroud)
代码:
use std::future::Future;
use std::task::{Context, Poll};
use std::pin::Pin;
use std::sync::{Arc,Mutex};
#[pin_project::pin_project]
struct Person<'a> {
name: &'a str,
age: i32,
}
impl<'a> Future for Person<'a> {
type Output = i32;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
*this.age += 1;
// error: poll() ^^^^ method not found in `impl Future`
// let mut fut1 = fn1();
// let a = fut1.poll(cx);
// error: Pin::new() ^^^^^^^^ within `impl Future`, the trait `Unpin` is not implemented for `from_generator::GenFuture
let mut fut1 = fn1();
let pinfut1 = Pin::new(&mut fut1);
let a = pinfut1.poll(cx);
if *this.age > 4 {
Poll::Ready(*this.age)
} else {
Poll::Pending
}
}
}
async fn fn1() -> i32 {
async_std::task::sleep(std::time::Duration::from_secs(2)).await;
123
}
fn main() {
let p1 = Person {name: "jack", age: Default::default()};
async_std::task::block_on(async {
let a = p1.await;
dbg!(a);
});
}
Run Code Online (Sandbox Code Playgroud)
要调用poll
whichfut1
返回的fn1
,您需要获取 a Pin<&mut F>
,其中F
是 future 的类型fut1
。至少有三种可能性可以做到这一点(我省略了unsafe
):
fut1
实现了Unpin
,你可以打电话Pin::new
,fut1
使用Box::pin
, 或fut1
使用宏固定堆栈futures_util::pin_mut!
。有时有点难以弄清楚是否Unpin
已实现,如果没有,那么为什么。fn1
这里的一般建议是对into:的签名进行脱糖fn fn1() -> impl Future<Output = usize> + Unpin
。编译器错误通常会更精确。
顺便说一句,宏的实现pin_mut!
有一些有用的见解。它使用 Rust 类型系统来移动 future 并隐藏变量,使其无法再被访问,通过这样做,它保证Pin::new_unchecked
满足 的不变量,因此可以调用它。
Anu*_*aki -3
我已将代码更改为以下内容,编译成功,但结果不正确:Future::poll() 中将通过 poll 方式调用 async fn,但 async fn 中的 .await 语句将永远被阻塞。
\nuse std::future::Future;\nuse std::task::{Context, Poll};\nuse std::pin::Pin;\nuse std::sync::{Arc,Mutex};\nuse futures::FutureExt;\n\n#[pin_project::pin_project]\nstruct Person<'a> {\n name: &'a str,\n age: i32,\n}\n\nimpl<'a> Future for Person<'a> {\n type Output = i32;\n\n fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n let mut this = self.project();\n *this.age += 10;\n\n let mut fut1 = fn1();\n let pinfut1 = Pin::new(&mut fut1);\n //let pinfut1 = unsafe { Pin::new_unchecked(&mut fut1) };\n pinfut1.poll(cx)\n }\n}\n\nfn fn1() -> impl Future<Output=i32> + Unpin {\n async {\n dbg!("sleep start!"); // execute here!\n async_std::task::sleep(std::time::Duration::from_secs(5)).await; // <--- blocked here ?\n dbg!("sleep done!"); // Never execute here\xef\xbc\x81\n 123\n }.boxed()\n}\n\nfn main() {\n let p1 = Person {name: "jack", age: Default::default()};\n async_std::task::block_on(async {\n let a = p1.await;\n dbg!(a); // Never execute here! // expect 123\n });\n std::thread::park();\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n