# Trabajo en background

> El patrón de threading de CrossFly — Thread/executor fuera de la paint thread, reingresando con onUI.

Source: https://crossfly.dev/es/docs/data-and-services/background-work — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Trabajo en background

Esta página consolida el patrón de threading que aparece en todas las anteriores, desde el punto de vista de
**quien escribe el trabajo pesado**. El "porqué" está en [La paint thread](/docs/concepts/the-paint-thread).

## La plantilla canónica
```java
new Thread(() -> {
   var resultado = trabalhoPesado();        // I/O o CPU — NUNCA en la paint thread
   meuComponente.onUI(() -> {               // reingresa en la paint thread
      mostrar(resultado);                    // tocar la UI solo aquí
      Component.repaint();
   });
}).start();
```
Formas de reingresar a la UI:
| Llamada | Uso |
|---|---|
| `Component.onUI(Runnable)` | desde cualquier thread, a partir de un componente |
| `Main.runOnPaintThread(Runnable)` | ídem, fuera del contexto de un componente |
| `Main.runOnPaintThreadAndWait(Runnable)` | ídem, **bloqueando** hasta terminar |

## Reaccionar a un evento de UI en un thread
Cuando el handler de un componente debe ejecutar trabajo pesado, use `onActionThread` (se ejecuta fuera de la paint
thread) y reingrese con `onUI`:
```java
botao.onActionThread(c -> {
   var dados = baixar();                    // fuera de la paint thread
   c.onUI(() -> lista.setItems(dados));     // vuelve a la UI
});
```

## Timers
Para trabajo periódico (polling, watchdog), use los timers del framework:
```java
comp.addTimer(1000);   // dispara un evento de timer cada 1000 ms (tratado en el componente)
```

## Utilidades de `util`
- **`ThreadSync`** — barrera de **2 threads** (productor/consumidor): `start()`/`start(maxMillis)`,
  `finished(resultado)`, `getResult()`. Útil para esperar un resultado de otro thread con timeout.
- **`RunnableWith<T>`** — callback con argumento: `void run(T obj)`. Es el tipo de los callbacks que
  entregan un valor (ej.: `onError` del `GPSThread`).

```java
ThreadSync sync = new ThreadSync();
new Thread(() -> { var r = calcular(); sync.finished(r); }).start();
sync.start(5000);                 // espera hasta 5 s
Object r = sync.getResult();
```

## Buenas prácticas
- **Todo** I/O bloqueante (DB, HTTP, GPS, BLE) se ejecuta **fuera** de la paint thread.
- Toque la UI **solamente** dentro de `onUI(...)`/`runOnPaintThread(...)`.
- Detenga threads/timers al salir de la pantalla (en `onRemove()`), o de lo contrario se filtran.

## Errores comunes
- Tocar widgets desde un `Thread` sin `onUI(...)` → comportamiento errático/bloqueo.
- `runOnPaintThreadAndWait(...)` llamado **desde dentro** de la paint thread (deadlock) — use la variante
  no bloqueante allí.
- Timers/threads no cancelados al cambiar de pantalla.

## Vea también
- Concepto: [La paint thread](/docs/concepts/the-paint-thread)
- [Gestión de estado](/docs/data-and-services/state-management) · [Red y HTTP](/docs/data-and-services/networking-http)
