02.1
为什么需要并发
UI 线程负责渲染与交互,耗时任务(解码、计算、网络)必须离开主线程,否则掉帧卡顿。
两类手段
TaskPool 适合大量短任务(自动调度、轻量);Worker 适合长驻或需持续通信的任务(独立线程)。
02.2
Promise 与 async
异步 API 返回 Promise,用 async/await 写成同步风格,避免回调嵌套。
async function load(): Promise<string> {
const data = await fetchSomething()
return data
}
// 并行
const [a, b] = await Promise.all([loadA(), loadB()])02.3
TaskPool
用 taskpool.execute 把纯函数派发到任务池执行,自动管理线程。
import taskpool from '@ohos.taskpool'
function compute(n: number): number { return n * n }
const task = new taskpool.Task(compute, 10)
taskpool.execute(task).then((r) => console.info(r))Task 需可序列化
TaskPool 跨线程传递参数,入参与返回值需可序列化,闭包捕获也受限制。
02.4
Worker
Worker 是独立线程,通过 postMessage/onmessage 与宿主通信,适合长驻任务。
// main
const worker = new worker.ThreadWorker("entry/ets/workers/myworker.ts")
worker.postMessage({ cmd: "start" })
worker.onmessage = (e) => console.info(e.data)
// worker.ts
workerPort.onmessage = (e) => workerPort.postMessage("done")02.5
任务取消
长时间任务应支持取消,避免资源浪费。TaskPool 任务可持有句柄取消;Worker 用消息通知退出。
const task = new taskpool.Task(compute, 10)
const res = taskpool.execute(task)
task.cancel() // 请求取消02.6
线程安全
跨线程共享状态需谨慎,优先通过消息传递(而非共享内存)交换数据,避免竞态。
02.7
与 UI 协作
并发结果回到主线程后更新 @State,由 ArkUI 自动刷新。
@State result: string = ""
aboutToAppear() {
taskpool.execute(new taskpool.Task(fetchText))
.then((r) => this.result = r as string)
}02.8
常见陷阱
TaskPool 任务在另一线程执行,无法访问 UI 组件实例。把所需数据作为参数传入,结果回传主线程再更新状态。
Worker 是常驻线程,不主动 terminate 会持续占用资源。任务结束后调用 worker.terminate() 释放。
02.9