繁体   English   中英

Tokio 非阻塞后台任务导致错误 `self` has an anonymous living `'_` 但它需要满足 `'static` 生存期要求

[英]Tokio non blocking background task leads to error `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement

我有一个异步 function 我想在后台运行。 此 function 是不使用异步调用的调用层次结构的一部分。

我的调用层次结构如下所示:

struct Handler {}
impl Handler {

  pub async fn handle(&self) {
     /// does some stuff and updates internal caches
  }
}

struct Client_v2 {
  handler: Handler,
  rt: tokio::runtime::Runtime,
}

impl Client_v2 {

  fn do_work(&self) {
    let future = self.handler(handle);
    self.rt.spawn(future); // want this to run in background and not block! 
    // `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  }
}

据我了解,存在一些问题,客户端可能会比其所有者Client_v2 ,从而导致此错误。

我应该如何让这个生命周期有效? 我是否需要求助于创建线程并将对象移入和移出线程 scope? 这个 function 调用非常频繁。

首先, handler是不可调用的,它是Client_v2的成员结构。 您需要通过点运算符访问它: self.handler.handle()

关于实际问题:

Runtime::spawn要求提供的 future 是'static + Send ,即它不能借用数据并且必须可以将其移动到另一个线程。

'static要求是由于父线程可能在线程执行未来之前退出,因此必须确保提供给任务的任何数据至少与任务本身一样长。

它必须是可Send的,因为tokio运行时可以在其线程池的线程之间自由移动spawn ed Future

您的错误的相关要求是第一个,由Handler::handle产生的未来不是'static的,因为 function 借用self作为共享参考: async fn handle(&self) 调用此 function 会产生一个Future + 'a ,其中'a&'a self的生命周期,即您可以将整个签名写为fn handle<'a>(&'a self) -> impl Future<Output=()> + 'a + Send但是Runtime::spawn需要你返回impl Future<Output=()> + 'static + Send

为了证明您没有从handle中的&self借用数据,您可以使用async {}块并明确 state 返回类型为impl Future<Output = ()> + Send + 'static

  pub fn handle(&self) -> impl Future<Output = ()> + 'static + Send {
      async {}
  }

如果您确实需要从async块内的&self访问数据,则需要在异步块之外生成它并将其移动到内部 - 否则生成的未来将再次违反'static要求”。

  pub fn handle(&self) -> impl Future<Output = ()> + 'static + Send {
      let owned_data = self.prepare_data();
      async move {
          let _owned_data = owned_data; // can now work with `owned_data`
      }
  }

或者@sebpuetz 回答。 在 rust 中,您可以将您的类型包装在Arc中,以便能够共享其 state,因此您可以将其(Arc 的克隆)移动到您需要计算的未来:

struct Client_v2 {
  handler: Handler,
  rt: tokio::runtime::Runtime,
}

impl Client_v2 {

  pub async fn handle(&self) {
  }
  
  fn do_work(self: Arc<Self>) {
    let handler = self.clone();
    let future = async move { handler.handle().await; };
    self.rt.spawn(future);
  }
}

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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