# 后台工作

> CrossFly 的线程模型 —— 在绘制线程之外使用 Thread/executor，再通过 onUI 返回。

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

# 后台工作

本页面从 **编写繁重工作者** 的视角出发，整合了在之前所有页面中都出现的线程模型。“为什么” 请参见
[绘制线程](/docs/concepts/the-paint-thread)。

## 标准模板
```java
new Thread(() -> {
   var resultado = trabalhoPesado();        // I/O 或 CPU — 绝不在 paint thread 上
   meuComponente.onUI(() -> {               // 重新进入 paint thread
      mostrar(resultado);                    // 仅在此处操作 UI
      Component.repaint();
   });
}).start();
```
返回 UI 的方式：
| 调用 | 用途 |
|---|---|
| `Component.onUI(Runnable)` | 从任意线程，基于某个组件 |
| `Main.runOnPaintThread(Runnable)` | 同上，但不在某个组件的上下文中 |
| `Main.runOnPaintThreadAndWait(Runnable)` | 同上，**阻塞** 直到完成 |

## 在线程中响应 UI 事件
当某个组件的处理程序需要运行繁重工作时，使用 `onActionThread`（在绘制线程之外运行），
再通过 `onUI` 返回：
```java
botao.onActionThread(c -> {
   var dados = baixar();                    // 不在 paint thread 中
   c.onUI(() -> lista.setItems(dados));     // 回到 UI
});
```

## 定时器
对于周期性工作（轮询、看门狗），使用框架的定时器：
```java
comp.addTimer(1000);   // 每 1000 ms 触发一次计时器事件（由组件处理）
```

## `util` 中的工具
- **`ThreadSync`** —— **2 个线程** 的屏障（生产者/消费者）：`start()`/`start(maxMillis)`，
  `finished(resultado)`、`getResult()`。用于带超时地等待另一个线程的结果。
- **`RunnableWith<T>`** —— 带参数的回调：`void run(T obj)`。它是那些
  传递值的回调的类型（例如：`GPSThread` 的 `onError`）。

```java
ThreadSync sync = new ThreadSync();
new Thread(() -> { var r = calcular(); sync.finished(r); }).start();
sync.start(5000);                 // 最多等待 5 秒
Object r = sync.getResult();
```

## 最佳实践
- **所有** 阻塞式 I/O（DB、HTTP、GPS、BLE）都在绘制线程 **之外** 运行。
- **仅** 在 `onUI(...)`/`runOnPaintThread(...)` 内部操作 UI。
- 离开屏幕时（在 `onRemove()` 中）停止线程/定时器，否则会泄漏。

## 常见错误
- 从 `Thread` 中未经 `onUI(...)` 操作控件 → 行为异常/卡死。
- 在绘制线程 **内部** 调用 `runOnPaintThreadAndWait(...)`（死锁）—— 在那里请使用
  非阻塞的变体。
- 切换屏幕时未取消定时器/线程。

## 另请参阅
- 概念：[绘制线程](/docs/concepts/the-paint-thread)
- [状态管理](/docs/data-and-services/state-management) · [网络与 HTTP](/docs/data-and-services/networking-http)
