1# Synchronous Task Development (TaskPool and Worker) 2 3 4Synchronous tasks are executed in order among multiple threads. Synchronization primitives, such as locks, are used by these tasks for coordination between each other. 5 6 7To implement synchronous tasks, you must consider the collaboration and synchronization between multiple threads and ensure the correctness of data and program execution. 8 9If synchronous tasks are independent of each other, you are advised to use **TaskPool**, which focuses on single independent tasks. For example, a series of imported static methods or methods implemented in singletons are independent. If synchronous tasks are associated with each other, use **Worker**, for example, methods implemented in class objects (not singleton class objects). 10 11 12## Using TaskPool to Process Independent Synchronous Tasks 13 14**TaskPool** is recommended for scheduling independent tasks. Typical independent tasks are those using static methods. If a unique handle or class object constructed using a singleton points to multiple tasks and these tasks can be used between different worker threads, you can also use **TaskPool**. 15 16> **NOTE** 17> 18> Due to the memory isolation feature between different threads in the [Actor model](multi-thread-concurrency-overview.md#actor-model), common singletons cannot be used between different threads. This issue can be solved by exporting a singleton through the sendable module. 19 201. Define concurrent functions to implement service logic. 21 222. Create a task [Task](../reference/apis-arkts/js-apis-taskpool.md#task) and execute the task through the [execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute-1) interface. 23 243. Perform operations on the task result. 25 26In the following example, the service uses TaskPool to call the code of the related synchronization method. Define the concurrent function taskpoolFunc first. Note that the function must be decorated by the [@Concurrent decorator](taskpool-introduction.md#concurrent-decorator). Define the mainFunc function. This function is used to create and execute a task and perform operations on the returned result of the task. 27 28 29```ts 30// Index.ets code 31import { taskpool} from '@kit.ArkTS'; 32 33// Step 1: Define a concurrent function to implement the service logic. 34@Concurrent 35async function taskpoolFunc(num: number): Promise<number> { 36 // Implement the corresponding function based on the service logic. 37 let tmpNum: number = num + 100; 38 return tmpNum; 39} 40 41async function mainFunc(): Promise<void> { 42 // Step 2: Create and execute a task. 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 // Step 3: Perform operations on the returned task result. 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## Using Worker to Process Associated Synchronous Tasks 76 77Use **Worker** when you want to schedule a series of synchronous tasks using the same handle or depending on the same class object. 78 791. Create a **Worker** object in the main thread and receive messages from the worker thread. DevEco Studio supports one-click Worker generation. Right-click any position in the {moduleName} directory and choose New > Worker from the shortcut menu to automatically generate the Worker template file and configuration information. 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 // Receive the result of the worker thread. 100 } 101 w.onerror = (): void => { 102 // Receive error information of the worker thread. 103 } 104 // Send a Set message to the worker thread. 105 w.postMessage({'type': 0, 'data': 'data'}) 106 // Send a Get message to the worker thread. 107 w.postMessage({'type': 1}) 108 // ... 109 // Select a time to destroy the thread based on the actual situation. 110 w.terminate() 111 }) 112 } 113 .width('100%') 114 } 115 .height('100%') 116 } 117 } 118 ``` 119 120 1212. Bind the **Worker** object in the worker thread and process the synchronous task logic. 122 123 ```ts 124 // handle.ts code 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 code 138 import { worker, ThreadWorkerGlobalScope, MessageEvents } from '@kit.ArkTS'; 139 import Handle from './handle' // Return a handle. 140 141 let workerPort : ThreadWorkerGlobalScope = worker.workerPort; 142 143 // Handle that cannot be transferred. All operations depend on this handle. 144 let handler: Handle = new Handle() 145 146 // onmessage() logic of the worker thread. 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