Saltar al contenido

Cómo se vuelve al hilo principal

La función que encola trabajo en el hilo de la interfaz, qué hay que tener en cuenta al usarla, y las dos alternativas que casi siempre son mejores: emitir un evento o no salir nunca.

La función

Rust
// desde cualquier hiloapp.run_on_main_thread(move || {    // aquí ya estamos en el hilo principal: se puede tocar la ventana    if let Some(w) = app_clon.get_webview_window("main") {        let _ = w.set_title("Indexado terminado");    }})?;

Y existe también sobre una ventana concreta, que es lo mismo con el destino ya elegido.

Las tres propiedades

La tercera es la que se ignora y produce un efecto contraintuitivo: encolar trabajo pesado en el hilo principal congela la interfaz igual que un comando síncrono. El bloque tiene que ser lo mínimo: leer no, calcular no, esperar no. Solo la llamada de interfaz.

Recuperar un resultado

Cuando de verdad hace falta —preguntar la posición de la ventana desde una tarea, por ejemplo— el patrón es un canal de un solo uso:

Rust
let (tx, rx) = tokio::sync::oneshot::channel();app.run_on_main_thread(move || {    let pos = ventana.outer_position().ok();    let _ = tx.send(pos);})?;let pos = rx.await.ok().flatten();

Funciona, y cada vez que lo escribas conviene preguntarse si hacía falta. Si una tarea de fondo necesita saber dónde está la ventana, casi siempre es que está tomando una decisión que no le corresponde.

Las dos alternativas

1 · Emitir un evento y que el frontend lo haga. Es la mejor y la que aplica más veces:

Rust
// en vez de tocar la ventana desde la tarea…app.emit(eventos::INDEXADO_FIN, &resumen)?;// …y el frontend cambia el título, muestra un aviso, o lo que corresponda

Tres ventajas: no hay que pensar en hilos, el cambio de interfaz lo decide el frontend —que es de quien es—, y funciona igual con varias ventanas.

2 · Hacerlo en el gancho de inicialización o en un comando. Los dos corren en un contexto donde el framework ya se ocupa del hilo. Si el cambio de interfaz puede esperar a que alguien lo pida, ahí es más simple.

Cuándo sí hace falta la función: cuando el core tiene que tocar la interfaz por su cuenta y ya, sin que haya nadie escuchando. El caso típico es reaccionar a algo del sistema: un enlace profundo que llega, un evento de la bandeja, una actualización que exige mostrar una ventana. Ahí puede que no haya frontend vivo a quien avisar.