1# 同步任务开发指导 (TaskPool和Worker) 2 3 4同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。 5 6 7同步任务的实现需要考虑多个线程之间的协作和同步,以确保数据的正确性和程序的正确执行。 8 9由于TaskPool偏向于单个独立的任务,因此当各个同步任务之间相对独立时推荐使用TaskPool,例如一系列导入的静态方法,或者单例实现的方法。如果同步任务之间有关联性,则需要使用Worker,例如无法单例创建的类对象实现的方法。 10 11 12## 使用TaskPool处理同步任务 13 14当调度独立的任务,或者一系列任务为静态方法实现,或者可以通过单例构造唯一的句柄或类对象,可在不同任务线程之间使用时,推荐使用TaskPool。 15 16> **说明:** 17> 18> 由于[Actor模型](multi-thread-concurrency-overview.md#actor模型)不同线程间内存隔离的特性,普通单例无法在不同线程间使用。可以通过共享模块导出单例解决该问题。 19 201. 定义并发函数,实现业务逻辑。 21 222. 创建任务[Task](../reference/apis-arkts/js-apis-taskpool.md#task),通过[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute-1)接口执行该任务。 23 243. 对任务返回的结果进行操作。 25 26如下示例中业务使用TaskPool调用相关同步方法的代码,首先定义并发函数taskpoolFunc,需要注意必须使用[@Concurrent装饰器](taskpool-introduction.md#concurrent装饰器)装饰该函数;其次定义函数mainFunc,该函数功能为创建任务,执行任务并对任务返回的结果进行操作。 27 28 29```ts 30// Index.ets代码 31import { taskpool} from '@kit.ArkTS'; 32 33// 步骤1: 定义并发函数,实现业务逻辑 34@Concurrent 35async function taskpoolFunc(num: number): Promise<number> { 36 // 根据业务逻辑实现相应的功能 37 let tmpNum: number = num + 100; 38 return tmpNum; 39} 40 41async function mainFunc(): Promise<void> { 42 // 步骤2: 创建任务并执行 43 let task1: taskpool.Task = new taskpool.Task(taskpoolFunc, 1); 44 let res1: number = await taskpool.execute(task1) as number; 45 let task2: taskpool.Task = new taskpool.Task(taskpoolFunc, res1); 46 let res2: number = await taskpool.execute(task2) as number; 47 // 步骤3: 对任务返回的结果进行操作 48 console.info("taskpool: task res1 is: " + res1); 49 console.info("taskpool: task res2 is: " + res2); 50} 51 52@Entry 53@Component 54struct Index { 55 @State message: string = 'Hello World'; 56 57 build() { 58 Row() { 59 Column() { 60 Text(this.message) 61 .fontSize(50) 62 .fontWeight(FontWeight.Bold) 63 .onClick(async () => { 64 mainFunc(); 65 }) 66 } 67 .width('100%') 68 .height('100%') 69 } 70 } 71} 72``` 73 74 75## 使用Worker处理关联的同步任务 76 77当一系列同步任务需要使用同一个句柄调度,或者需要依赖某个类对象调度,无法在不同任务池之间共享时,需要使用Worker。 78 791. 在UI主线程中创建Worker对象,同时接收Worker线程发送回来的消息。DevEco Studio支持一键生成Worker,在对应的{moduleName}目录下任意位置,点击鼠标右键 > New > Worker,即可自动生成Worker的模板文件及配置信息。 80 81 ```ts 82 // Index.ets 83 import { worker } from '@kit.ArkTS'; 84 85 @Entry 86 @Component 87 struct Index { 88 @State message: string = 'Hello World'; 89 90 build() { 91 Row() { 92 Column() { 93 Text(this.message) 94 .fontSize(50) 95 .fontWeight(FontWeight.Bold) 96 .onClick(() => { 97 let w: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts'); 98 w.onmessage = (): void => { 99 // 接收Worker子线程的结果 100 } 101 w.onerror = (): void => { 102 // 接收Worker子线程的错误信息 103 } 104 // 向Worker子线程发送Set消息 105 w.postMessage({'type': 0, 'data': 'data'}) 106 // 向Worker子线程发送Get消息 107 w.postMessage({'type': 1}) 108 // ... 109 // 根据实际业务,选择时机以销毁线程 110 w.terminate() 111 }) 112 } 113 .width('100%') 114 } 115 .height('100%') 116 } 117 } 118 ``` 119 120 1212. 在Worker线程中绑定Worker对象,同时处理同步任务逻辑。 122 123 ```ts 124 // handle.ts代码 125 export default class Handle { 126 syncGet() { 127 return; 128 } 129 130 syncSet(num: number) { 131 return; 132 } 133 } 134 ``` 135 136 ```ts 137 // MyWorker.ts代码 138 import { worker, ThreadWorkerGlobalScope, MessageEvents } from '@kit.ArkTS'; 139 import Handle from './handle'; // 返回句柄 140 141 let workerPort : ThreadWorkerGlobalScope = worker.workerPort; 142 143 // 无法传输的句柄,所有操作依赖此句柄 144 let handler: Handle = new Handle() 145 146 // Worker线程的onmessage逻辑 147 workerPort.onmessage = (e : MessageEvents): void => { 148 switch (e.data.type as number) { 149 case 0: 150 handler.syncSet(e.data.data); 151 workerPort.postMessage('success set'); 152 break; 153 case 1: 154 handler.syncGet(); 155 workerPort.postMessage('success get'); 156 break; 157 } 158 } 159 ``` 160