HarmonyOS ArkTS 并发编程实战:TaskPool 与 Worker 的选型与避坑
一、主线程不是用来做重活的
HarmonyOS 应用的 UI 渲染与事件分发都运行在主线程。一次耗时的 JSON 解析、一张大图解码、一段复杂计算,都可能让主线程掉帧,表现为滑动卡顿、点击延迟。ArkTS 提供了两种常用的并发能力:TaskPool 和 Worker。它们都能把任务移出主线程,但适用场景和约束并不相同。
二、TaskPool:轻量任务的优先选择
TaskPool 由框架统一管理线程池,开发者只需把函数标记为 @Concurrent,再通过 taskpool.execute 提交任务。线程的创建、复用和销毁由系统负责,不需要手动维护生命周期。
@Concurrent
function parseLargeJson(raw: string): number {
const data = JSON.parse(raw) as Array<Record<string, Object>>;
return data.length;
}
async function countRecords(raw: string): Promise<number> {
return await taskpool.execute(parseLargeJson, raw) as number;
}
需要注意三点:
- 被
@Concurrent标记的函数在子线程执行,不能直接访问 UI 上下文、组件实例或主线程的可变全局变量。 - 参数与返回值需要能够序列化,复杂对象建议先转成普通数据结构,避免携带不可序列化的句柄。
- 任务粒度要合理。把很小的计算拆成大量任务,线程调度开销可能超过计算本身。
三、Worker:需要长期驻留的场景
Worker 更像一个独立的工作线程,拥有自己的运行环境,通过消息机制与主线程通信。它适合需要保持状态、持续处理事件的场景,例如长连接的协议解析、音视频数据的持续处理。
// Worker 线程
import { worker, MessageEvents } from '@kit.ArkTS';
const workerPort = worker.workerPort;
workerPort.onmessage = (event: MessageEvents) => {
const payload = event.data as string;
const result = payload.length;
workerPort.postMessage(result);
};
Worker 的代价是需要自行管理生命周期。页面销毁时应及时终止,否则会留下后台线程,既占用内存,也让调试变得困难。
四、如何选型
可以用三个问题快速判断:
- 任务是否一次性、可并行拆分?如果是,优先 TaskPool。
- 任务是否需要长期保存上下文、持续接收消息?如果是,选择 Worker。
- 任务之间是否需要频繁共享中间状态?如果是,先考虑能否改造成消息传递,否则并发带来的复杂度可能得不偿失。
大多数业务场景,例如数据解析、图片压缩、加解密、批量计算,都属于第一类,TaskPool 已经足够。
五、几个容易踩的坑
坑一:在并发函数里访问 UI。 子线程无法直接操作组件状态。正确做法是把结果返回主线程,再由主线程更新状态变量。
坑二:传递闭包捕获的变量。 @Concurrent 函数只能使用入参和函数内部定义的变量。依赖外部闭包的值不会被带到子线程,运行时可能得到 undefined。
坑三:忽略异常。 子线程抛出的异常需要通过 Promise 的 reject 或 try/catch 捕获,否则表现为任务静默失败,排查成本很高。
坑四:任务未取消。 页面退出后,仍在队列中的任务可能继续执行并回调已销毁的页面。提交任务时保存 task 句柄,在 aboutToDisappear 中调用取消。
private task: taskpool.Task | null = null;
aboutToDisappear(): void {
if (this.task) {
taskpool.cancel(this.task);
this.task = null;
}
}
六、性能验证建议
并发改造后不要只看“是否不卡了”,建议做量化验证:
- 用 DevEco Studio 的 Profiler 观察主线程帧耗时,对比改造前后的掉帧率;
- 记录单个任务的执行时长与排队时长,判断瓶颈在计算还是在调度;
- 在低端设备上复测,线程池大小和 CPU 核数不同,表现可能差异明显。
七、小结
TaskPool 适合短时、可并行的计算任务,Worker 适合有状态、长驻留的处理逻辑。选型的关键不是哪种技术更“高级”,而是任务的生命周期与数据流形态。把重活移出主线程,把结果安全地送回主线程,再用数据验证收益,才是并发改造的完整闭环。
- 点赞
- 收藏
- 关注作者
评论(0)