繁体   English   中英

Tokio / Tonic - 如何修复此错误:`self` 有生命周期`'life0` 但它需要满足`'static` 生命周期要求

[英]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()中的Arcstream_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM