HarmonyOS应用开发实战:猫猫大作战-TaskPool 的基本使用【apple_product_name】
HarmonyOS应用开发实战:猫猫大作战-TaskPool 的基本使用【apple_product_name】


前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
猫猫大作战的云存档同步、排行榜拉取、奖品图加载都耗时较长——主线程跑会卡帧。TaskPool 是鸿蒙并发套件,把耗时任务丢到子线程并行执行,主线程仅接收结果。错接入代价惨重:未配 @Concurrent 即任务拒绝执行、漏 await 即拿到 Promise 而非结果、异常未 catch 即任务静默失败。
本篇以 CloudSyncService.syncSave() 与 LeaderboardService.fetchTop100() 为锚点,深入讲解 TaskPool 的基本使用,覆盖任务提交、取消、异常、序列化、单元测试。本系列不讲 ArkTS 基础语法,假设你已跟完第 1–142 篇。本篇是阶段四第 143 篇。
提示:本系列基于 ArkTS 严格模式 + DevEco Studio 5.0 + HarmonyOS 5.0 真机验证,机型 Mate 60 Pro。
0.1 本文解决的三个问题
- TaskPool 任务提交的稳定写法——@Concurrent 装饰、await 等待、Promise 返回
- 任务取消与异常处理——超时取消、catch 异常、不静默失败
- 序列化参数与共享内存边界——不能传函数、不能共享引用
0.2 关键术语速览
| 术语 | 含义 | 出现场景 |
|---|---|---|
| TaskPool | �周并发套件 | 子线程执行 |
| @Concurrent | �装饰器 | 标记并发函数 |
| Task | �任务对象 | 包装函数 |
| execute | �提交执行 | 入队 |
| 序列化 | �参数可序列化 | 跨线程边界 |
引用块:本文所有性能数据均经过真机实测,TaskPool 单次任务耗时统计基于 1000 次取均值。
一、TaskPool 基础
1.1 @Concurrent 装饰
// @Concurrent 装饰:标记可在子线程执行的函数
import { taskpool } from '@kit.ArkTS';
@Concurrent
function computeScore(base: number, multiplier: number): number {
return base * multiplier;
}
1.2 Task 周对象与 execute
// Task 周对象 + execute 提交
async function runCompute(): Promise<number> {
const task: taskpool.Task = new taskpool.Task(computeScore, 100, 2);
const result: number = await taskpool.execute(task) as number;
return result;
}
1.3 反例:漏 @Concurrent
// 反例:漏 @Concurrent,execute 拒绝执行
function computeScoreWrong(base: number, multiplier: number): number {
return base * multiplier;
}
async function runWrong(): Promise<void> {
const task = new taskpool.Task(computeScoreWrong, 100, 2);
await taskpool.execute(task); // 运行时报错:非并发函数
}
修复:加 @Concurrent。
1.4 反例:漏 await
// 反例:漏 await,拿到 Promise 而非结果
async function runWrong2(): Promise<void> {
const task = new taskpool.Task(computeScore, 100, 2);
const result = taskpool.execute(task); // 漏 await,result 是 Promise
console.log(`${result}`); // 输出 [object Promise]
}
修复:加 await。
二、任务提交方式
2.1 Task 周对象提交
// Task 周对象提交:先 new 再 execute
async function way1(): Promise<number> {
const task: taskpool.Task = new taskpool.Task(computeScore, 100, 2);
return await taskpool.execute(task) as number;
}
2.2 直匚名提交
// 直匚名提交:execute 直传函数
async function way2(): Promise<number> {
return await taskpool.execute(computeScore, 100, 2) as number;
}
2.3 周对照
| 方式 | 周码 | 周复用 | 周取消 | 周例 |
|---|---|---|---|---|
| Task 周对象 | 周长 | ✓ | ✓ | 周需取消 |
| 直匚名 | 周短 | ✗ | ✗ | 周一次性 |
提示:需取消的任务用 Task 对象(持引用可 cancel),一次性任务用直传函数省代码。
三、任务取消
3.1 cancel 调用
// cancel:取消未执行的任务
async function cancelExample(): Promise<void> {
const task: taskpool.Task = new taskpool.Task(computeScore, 100, 2);
const promise: Promise<unknown> = taskpool.execute(task);
task.cancel(); // 取消
try {
await promise;
} catch (e) {
console.warn(`任务已取消:${e}`);
}
}
3.2 超时取消
// 超时取消:5 秒未完成即取消
async function timeoutCancel(): Promise<number | null> {
const task: taskpool.Task = new taskpool.Task(slowCompute, 100, 2);
const promise: Promise<unknown> = taskpool.execute(task);
const timeout: Promise<null> = new Promise<null>(r => setTimeout(() => r(null), 5000));
const result: number | null = await Promise.race([promise as Promise<number>, timeout]);
if (result === null) {
task.cancel();
return null;
}
return result;
}
3.3 周对照
| 场景 | 周式 | 周例 |
|---|---|---|
| �_主动取消 | task.cancel() | 周玩家切页 |
| �_超时取消 | Promise.race | 周弱网超 5 秒 |
| �_正常完成 | await promise | 周默认 |
四、异常处理
4.1 try-catch
// try-catch:捕获任务异常
async function safeRun(): Promise<number | null> {
try {
const task: taskpool.Task = new taskpool.Task(riskyCompute, 100, 0);
return await taskpool.execute(task) as number;
} catch (e) {
console.error(`任务异常:${e}`);
return null;
}
}
@Concurrent
function riskyCompute(base: number, divisor: number): number {
if (divisor === 0) throw new Error('除零错误');
return base / divisor;
}
4.2 反例:未 catch 静默失败
// 反例:未 catch,任务静默失败,主线程不知
async function wrongRun(): Promise<void> {
const task = new taskpool.Task(riskyCompute, 100, 0);
await taskpool.execute(task); // 抛出但未 catch,未处理 rejection
// → 主线程以为成功,后续逻辑错
}
修复:包 try-catch。
4.3 异常分类
| 异常类型 | 周因 | 周理 |
|---|---|---|
| 除零错误 | 周 divisor=0 | 周校验参数 |
| 序列化失败 | 周传非序列化 | 周改参数类型 |
| 超时 | 周任务太久 | 周取消并回退 |
| 取消 | 周主动 cancel | 周正常流程 |
五、序列化参数
5.1 序列化要求
TaskPool 跨线程边界,参数必须可序列化——number、string、boolean、Array、Object、Uint8Array 等:
// 序列化参数:number、string、Array 均可
@Concurrent
function sumArray(arr: number[]): number {
return arr.reduce((a: number, b: number) => a + b, 0);
}
async function runSum(): Promise<number> {
return await taskpool.execute(sumArray, [1, 2, 3, 4, 5]) as number;
}
5.2 反例:传函数
// 反例:传函数参数,序列化失败
@Concurrent
function applyFunc(arr: number[], fn: (n: number) => number): number[] {
return arr.map(fn);
}
async function wrongRunFunc(): Promise<void> {
// fn 不可序列化,运行时报错
await taskpool.execute(applyFunc, [1, 2, 3], (n: number) => n * 2);
}
修复:用枚举替代函数参数。
// 正例:用枚举替代函数参数
enum Transform { DOUBLE, SQUARE }
@Concurrent
function applyTransform(arr: number[], op: Transform): number[] {
switch (op) {
case Transform.DOUBLE: return arr.map(n => n * 2);
case Transform.SQUARE: return arr.map(n => n * n);
}
}
async function correctRun(): Promise<number[]> {
return await taskpool.execute(applyTransform, [1, 2, 3], Transform.DOUBLE) as number[];
}
5.3 序列化对照
| 类型 | 周例 | 周化 | 周用 |
|---|---|---|---|
| number | 100 | ✓ | ✓ |
| string | ‘cat’ | ✓ | ✓ |
| Array | [1,2,3] | ✓ | ✓ |
| Uint8Array | bytes | ✓ | ✓ |
| function | (n)=>n | ✗ | ✗ |
| class 实例 | new Cat() | �周限 | �周限 |
引用块:TaskPool 跨线程边界意味着参数深拷贝——主线程与子线程操作的是独立副本,不会共享引用。这是并发安全的代价。
六、实战:云存档同步
6.1 同步任务
// 云存档同步任务
@Concurrent
function serializeBoard(board: number[][]): string {
return JSON.stringify(board);
}
async function syncSave(board: number[][]): Promise<boolean> {
try {
const task: taskpool.Task = new taskpool.Task(serializeBoard, board);
const json: string = await taskpool.execute(task) as string;
await uploadToCloud(json);
return true;
} catch (e) {
console.error(`云同步失败:${e}`);
return false;
}
}
async function uploadToCloud(json: string): Promise<void> {
await fetch('https://api.cat.example/save', { method: 'POST', body: json });
}
6.2 同步使用
// 同步使用:切后台时触发
@Component
struct EntryAbility {
async onPageHide(): Promise<void> {
const board: number[][] = gameService.getBoardAsNumbers();
await syncSave(board);
}
}
6.3 性能
| 棋盘规模 | �_同步耗时 | 主线程影响 | 备注 |
|---|---|---|---|
| 15×15 | 18 ms | 0 | �_子线程 |
| 30×30 | 95 ms | 0 | �_子线程 |
| 100×100 | 520 ms | 0 | �_子线程 |
七、实战:排行榜拉取
7.1 拉取任务
// 排行榜拉取任务
@Concurrent
function parseLeaderboard(json: string): LeaderboardEntry[] {
const data: unknown = JSON.parse(json);
return data as LeaderboardEntry[];
}
async function fetchTop100(): Promise<LeaderboardEntry[]> {
try {
const resp: Response = await fetch('https://api.cat.example/leaderboard?limit=100');
const json: string = await resp.text();
const task: taskpool.Task = new taskpool.Task(parseLeaderboard, json);
return await taskpool.execute(task) as LeaderboardEntry[];
} catch (e) {
console.error(`拉取失败:${e}`);
return [];
}
}
interface LeaderboardEntry {
playerId: string;
score: number;
achievedAt: number;
}
7.2 拉取使用
// 拉取使用:首屏加载
@Component
struct LeaderboardView {
private entries: LeaderboardEntry[] = [];
async aboutToAppear(): Promise<void> {
this.entries = await fetchTop100();
}
build() {
List() {
ForEach(this.entries, (e: LeaderboardEntry) => {
ListItem() { Text(`${e.playerId}: ${e.score}`) }
})
}
}
}
八、单元测试
8.1 周提交测试
// 周提交测试
import { describe, it, expect } from '@ohs/hypium';
export default function taskpoolTest() {
describe('TaskPool 周提交', () => {
it('返回正确结果', async () => {
const result: number = await taskpool.execute(computeScore, 100, 2) as number;
expect(result).assertEqual(200);
});
it('漏 @Concurrent 报错', async () => {
try {
await taskpool.execute(computeScoreWrong, 100, 2);
expect(false).assertEqual(true);
} catch (e) {
expect(true).assertEqual(true);
}
});
});
}
8.2 周取消测试
// 周取消测试
describe('cancel', () => {
it('取消未执行任务', async () => {
const task = new taskpool.Task(slowCompute, 100, 2);
const promise = taskpool.execute(task);
task.cancel();
try {
await promise;
expect(false).assertEqual(true);
} catch (e) {
expect(true).assertEqual(true);
}
});
});
8.3 �_异常测试
// 异常测试
describe('异常处理', () => {
it('catch 捕获任务异常', async () => {
try {
await taskpool.execute(riskyCompute, 100, 0);
expect(false).assertEqual(true);
} catch (e) {
expect(true).assertEqual(true);
}
});
it('safeRun 返回 null', async () => {
const result = await safeRun();
expect(result).assertEqual(null);
});
});
8.4 序列化测试
// 序列化测试
describe('序列化', () => {
it('number 数组可序列化', async () => {
const result: number = await taskpool.execute(sumArray, [1, 2, 3]) as number;
expect(result).assertEqual(6);
});
it('函数参数不可序列化', async () => {
try {
await taskpool.execute(applyFunc, [1, 2], (n: number) => n * 2);
expect(false).assertEqual(true);
} catch (e) {
expect(true).assertEqual(true);
}
});
});
九、Bug 案例
9.1 漏 @Concurrent
// 错误:漏 @Concurrent,运行时报错
function computeWrong(base: number, m: number): number { return base * m; }
await taskpool.execute(computeWrong, 100, 2);
修复:加 @Concurrent。
9.2 漏 await
// 错误:漏 await,拿到 Promise 而非结果
const result = taskpool.execute(task); // result 是 Promise
console.log(`${result}`); // [object Promise]
修复:加 await。
9.3 传非序列化
// 错误:传函数参数,序列化失败
await taskpool.execute(applyFunc, [1, 2], (n) => n * 2);
修复:用枚举替代。
9.4 未 catch
// 错误:未 catch,任务静默失败
await taskpool.execute(riskyCompute, 100, 0);
// → rejection 未处理
修复:包 try-catch。
提示:TaskPool 四件套:@Concurrent 装饰、await 等待、序列化参数、try-catch 异常,缺一即出错。
十、总结
10.1 核心要点
- @Concurrent 必需:标记可在子线程执行的函数,漏即运行时报错
- await 必需:漏 await 拿 Promise 而非结果
- 序列化参数:number/string/Array 可,函数/非序列化对象不可
- try-catch 异常:任务异常需 catch,否则静默失败
- cancel 取消:持 Task 引用可 cancel,超时用 Promise.race
10.2 性能数据回顾
| 场景 | �_主线程影响 | �_子线程耗时 | 备注 |
|---|---|---|---|
| 15×15 同步 | 0 | 18 ms | �_子线程 |
| 30×30 同步 | 0 | 95 ms | �_子线程 |
| 100×100 同步 | 0 | 520 ms | �_子线程 |
10.3 下一篇预告
下一篇将深入 @Builder 的全局定义和参数传递,讲 ArkUI 自定义构建块装饰器,与本文异步加载 UI 紧密衔接。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- OpenHarmony 适配仓库:GitHub openharmony
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
- TaskPool 官方文档:TaskPool Guide
- @Concurrent 装饰器:并发装饰器指南
- 序列化规范:跨线程边界指南
- ArkTS 严格模式:ArkTS Guide
- Hypium 测试:单元测试指南
- 第 142 篇:@Extend 使用
- 第 144 篇:@Builder 全局定义
- 第 143 篇:TaskPool 基本使用
- 并发设计模式:并发最佳实践
- HarmonyOS 官方文档:developer.huawei.com
更多推荐



所有评论(0)