![](/img/trans.png)
[英]error : self has an anonymous lifetime '_ but it needs to satisfy a 'static lifetime requirement
[英]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.