本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、TaskPool 线程通信
1. 场景
-
实时状态通知:任务执行过程中需要定时向宿主线程报告进度
-
分段数据返回:处理大量数据时分段返回,避免长时间等待
-
中间结果获取:在任务完成前获取部分计算结果
2. 与传统方式的区别
| 通信方式 | 返回时机 | 数据形式 | 适用场景 |
|---|---|---|---|
| 传统execute() | 任务完成后一次性返回 | 最终结果 | 简单任务 |
| sendData()通信 | 任务执行过程中多次返回 | 进度、分段数据 | 复杂长任务 |
二、线程通信的实现机制
1. 核心通信接口
-
发送端:
taskpool.Task.sendData()- 在任务线程中发送数据 -
接收端:
task.onReceiveData()- 在宿主线程中接收数据 -
回调函数:用户定义的消息处理函数
三、实现步骤
步骤1:定义数据模型
// ImageDataModel.ets
export class ImageItem {
imageUrl: string | Resource = '';
title: string | Resource = '';
constructor(imageUrl: string | Resource = '', title: string | Resource = '') {
this.imageUrl = imageUrl;
this.title = title;
}
}
步骤2:创建消息接收处理函数
// TaskCommunication.ets
export function handleProgressUpdate(progressData: number): void {
// 处理从任务线程接收到的进度数据
console.info("后台任务执行进度: ", progressData);
// 可以在这里更新UI进度条、显示提示信息等
}
步骤3:实现支持通信的任务函数
// TaskCommunication.ets
import { taskpool } from '@kit.ArkTS';
import { ImageItem } from './ImageDataModel';
@Concurrent
export function processImagesWithProgress(imageCount: number): ImageItem[] {
let processedImages: ImageItem[] = [];
// 模拟处理多个图片
for (let i = 0; i < imageCount; i++) {
const batchStart = i * 3;
// 添加图片数据到结果列表
processedImages.push(new ImageItem('$media:homeIcon', `图片${batchStart + 1}`));
processedImages.push(new ImageItem('$media:galleryIcon', `图片${batchStart + 2}`));
processedImages.push(new ImageItem('$media:documentIcon', `图片${batchStart + 3}`));
// 关键:发送进度更新到宿主线程
const currentProgress = processedImages.length;
taskpool.Task.sendData(currentProgress);
// 模拟耗时操作
if (i % 4 === 0) {
console.info(`已处理 ${currentProgress} 张图片`);
}
}
return processedImages;
}
步骤4:在宿主线程中配置和使用
// MainPage.ets
import { taskpool } from '@kit.ArkTS';
import { ImageItem } from './ImageDataModel';
import { processImagesWithProgress, handleProgressUpdate } from './TaskCommunication';
@Entry
@Component
struct MainPage {
@State pageTitle: string = '图片处理进度演示';
@State progressInfo: string = '准备开始';
@State finalResult: ImageItem[] = [];
@State currentProgress: number = 0;
@State totalItems: number = 0;
build() {
Column() {
Text(this.pageTitle)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text(this.progressInfo)
.fontSize(16)
.fontColor(Color.Blue)
.margin({ bottom: 20 })
Text(`处理进度: ${this.currentProgress} 项`)
.fontSize(14)
.margin({ bottom: 10 })
Button('开始处理图片')
.fontSize(18)
.padding(10)
.backgroundColor(Color.Green)
.onClick(() => {
this.startImageProcessing();
})
.margin({ bottom: 20 })
if (this.finalResult.length > 0) {
Text(`处理完成,共 ${this.finalResult.length} 张图片`)
.fontSize(16)
.fontColor(Color.Green)
}
}
.padding(20)
.width('100%')
}
private async startImageProcessing(): Promise<void> {
try {
// 重置状态
this.progressInfo = '开始处理图片...';
this.currentProgress = 0;
this.finalResult = [];
// 创建任务实例
const imageProcessingTask: taskpool.Task = new taskpool.Task(processImagesWithProgress, 25);
// 关键:设置数据接收回调函数
imageProcessingTask.onReceiveData(this.handleTaskData.bind(this));
// 执行任务
this.finalResult = await taskpool.execute(imageProcessingTask) as ImageItem[];
// 任务完成后的处理
this.progressInfo = `图片处理完成!总共 ${this.finalResult.length} 张`;
this.totalItems = this.finalResult.length;
console.info(`最终结果: 共处理 ${this.finalResult.length} 张图片`);
} catch (error) {
console.error(`图片处理失败: ${error}`);
this.progressInfo = '处理失败,请重试';
}
}
private handleTaskData(progressData: number): void {
// 更新进度状态
this.currentProgress = progressData;
this.progressInfo = `正在处理... 已完成 ${progressData} 项`;
// 可以在这里添加更多的进度处理逻辑
if (progressData % 20 === 0) {
console.info(`进度更新: 已完成 ${progressData} 项操作`);
}
}
}
四、技术细节
1. sendData() 方法特性
// 在 @Concurrent 函数中使用
@Concurrent
function exampleTask(param: number): ResultType {
// 处理逻辑...
// 发送进度数据(支持基本数据类型)
taskpool.Task.sendData(progressValue);
// 继续处理...
return finalResult;
}
支持的数据类型:
-
number、string、boolean 等基本类型
-
支持序列化的对象
-
注意:数据量应符合序列化限制(16MB)
2. onReceiveData() 回调配置
// 回调函数签名要求
type DataCallback = (data: any) => void;
// 配置回调的时机
const task = new taskpool.Task(taskFunction, ...args);
// 必须在 execute() 之前设置回调
task.onReceiveData((progress) => {
// 处理接收到的数据
updateProgressBar(progress);
});
// 然后执行任务
await taskpool.execute(task);
五、通信机制
1. 数据流方向
任务线程 (TaskPool Worker)
↓ 通过 taskpool.Task.sendData()
消息队列
↓ 通过 task.onReceiveData()
宿主线程 (UI Thread)
↓ 调用回调函数
用户界面更新
2. 线程安全保证
-
消息传递是线程安全的
-
数据会自动序列化和反序列化
-
回调函数在宿主线程中执行,可以安全更新UI
六、总结
-
使用
taskpool.Task.sendData()在任务线程中发送数据 -
使用
task.onReceiveData()在宿主线程中接收数据 -
确保在调用
execute()之前设置好回调函数 -
合理控制消息发送频率,平衡实时性和性能
1043

被折叠的 条评论
为什么被折叠?



