[英]Tokio non blocking background task leads to error `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
[英]Tokio / Tonic - How to fix this error: `self` has lifetime `'life0` but it needs to satisfy a `'static` lifetime requirement
我正在使用 Rust 和 tonic 构建一个 gRPC 服务器,并且在返回流的函数方面存在一些问题。 到目前为止,我看到的唯一示例在函数中方便地创建了 tx 和 rx 通道 - 但如果您需要从应用程序的其他部分接收数据,这并没有太大帮助。 我有以下代码,但出现错误。
代码
use std::sync::Arc;
use std::sync::Mutex;
use futures::{Stream, StreamExt};
use tokio::sync::mpsc;
use tokio::sync::mpsc::{Sender, Receiver};
use tokio_stream::wrappers::ReceiverStream;
use tonic::transport::Server;
use tonic::{Request, Response, Status};use resourcemanager::{LineRequest, LineResponse, Position};
use resourcemanager::resource_manager_server::{ResourceManager, ResourceManagerServer};
pub mod resourcemanager {
tonic::include_proto!("resourcemanager");
}
#[derive(Debug)]
pub struct ResourceManagerService {
linear_rx: mpsc::Receiver<Position>,
linear_tx: mpsc::Sender<Position>
}
#[tonic::async_trait]
impl ResourceManager for ResourceManagerService {
async fn draw_line(&self, request: Request<LineRequest>) -> Result<Response<LineResponse>, Status> {
Ok(Response::new(LineResponse::default()))
}
type StreamLinearMotorMovementStream = ReceiverStream<Result<Position, Status>>;
async fn stream_linear_motor_movement(
&self,
request: Request<()>
) -> Result<Response<Self::StreamLinearMotorMovementStream>, Status> {
println!("Streaming motor movements");
let (tx, mut rx) = mpsc::channel(1);
tokio::spawn(async move {
while let Some(received) = self.linear_rx.recv().await {
tx.send(Ok(received.clone())).await.unwrap();
}
});
Ok(Response::new(ReceiverStream::new(rx)))
}
}
fn main() {
println!("Hello, world!");
}
错误
error[E0759]: `self` has lifetime `'life0` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:30:10
|
30 | &self,
| ^^^^ this data with lifetime `'life0`...
...
36 | tokio::spawn(async move {
| ------------ ...is used and required to live as long as `'static` here
|
note: `'static` lifetime requirement introduced by this bound
--> /Users/xxxxxxxx/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.18.2/src/task/spawn.rs:127:28
|
127 | T: Future + Send + 'static,
| ^^^^^^^
此错误显示在&self
下方:
async fn stream_linear_motor_movement(
&self,
request: Request<()>
)
错误消息基本上说明了一切。 缩写:
async fn stream_linear_motor_movement(&self) {
let (tx, mut rx) = mpsc::channel(1);
tokio::spawn(async move {
while let Some(received) = self.linear_rx.recv().await {}
});
}
新生成的任务中的片段self.linear_rx.recv().await
强制编译器将self
移动到该闭包中,因此闭包可以访问self.linear_rx
。 然而,由于新任务可以永远运行,它要求其捕获的上下文具有'static
的生命周期,而&self
的生命周期是有限的,可能比'static
life0
(无论结果如何)。 这意味着您不能从新生成的任务中访问self
(或从它派生的任何内容),因为无法保证在任务执行时它会存在。
您可以做的是将ResourceManagerService
中的linear_rx
移动到Arc
中, .clone()
中的Arc
在stream_linear_motor_movement
中,然后将该克隆移动到闭包中。 根据您要完成的任务,您还可以将linear_rx
移动到Option
和.take()
该Option
中的stream_linear_motor_movement
中,将None
留在它的位置。 在这两种情况下,您都将拥有的对象转移到新生成的任务中,该任务的生命周期不短于'static
。 请注意, Arc
将允许一个调用stream_linear_motor_movement
多次,而Option
只允许一个调用它恰好一次(因为linear_rx
在第一次调用时被移走)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.