es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La tarea de fondo no bloqueante de Tokio provoca el error `self` tiene una vida anónima `’_` pero debe cumplir con un requisito de vida útil `static`.

Tengo una función asíncrona que quiero ejecutar en segundo plano. Esta función forma parte de una jerarquía de llamadas que no está utilizando llamadas asíncronas.

Mi jerarquía de llamadas se ve así:

struct Handler {}
impl Handler {

pub async fn handle(&self) {
     /// hace algunas cosas y actualiza cachés internas
  }
}

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); // ¡quiero que esto se ejecute en segundo plano y no bloquee!
    // <code>self</code> tiene una duración anónima <code>'_</code>, pero necesita cumplir un requisito de duración <code>'static</code>
  }
}

Por lo que entiendo, hay un problema en el que tal vez el cliente podría sobrevivir a su propietario Client_v2, lo que lleva a este error.

¿Cómo debería hacer que esta duración sea válida? ¿Necesito recurrir a la creación de hilos y mover objetos dentro y fuera del ámbito del hilo? Esta función se llama con mucha frecuencia.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para hacer que la duración sea válida, puedes usar el puntero inteligente Arc (conteo de referencias atómico) para crear una propiedad compartida de la instancia Handler. Luego, puedes mover la instancia Arc<handler> dentro de la clausura que se pasa a self.rt.spawn, lo cual asegurará que la clausura pueda acceder a la instancia Handler mientras la clausura se esté ejecutando.

    Aquí está la implementación actualizada:

    use std::sync::Arc;
    
    struct Handler {}
    
    impl Handler {
        pub async fn handle(&self) {
            /// realiza algunas tareas y actualiza las cachés internas
        }
    }
    
    struct Client_v2 {
        handler: Arc<handler>,
        rt: tokio::runtime::Runtime,
    }
    
    impl Client_v2 {
        fn do_work(&self) {
            let handler = self.handler.clone();
            let future = async move {
                handler.handle().await;
            };
            self.rt.spawn(future); // se ejecutará en segundo plano y no bloqueará
        }
    }
    

    En esta implementación, creamos una instancia de Arc<handler> en lugar de Handler y también actualizamos la implementación de do_work para crear un clon de Arc<handler> utilizando el método clone(). Luego, movemos la instancia clonada de Arc<handler> dentro de la clausura que se pasa a self.rt.spawn utilizando la sintaxis async move.

Comments are closed.