1# Synchronous Task Development (TaskPool and Worker) 2 3 4Synchronous tasks involve coordinating execution across multiple threads to ensure that tasks run in a specific order and adhere to certain rules, such as using locks to prevent data races. 5 6 7To implement synchronous tasks, you must consider the collaboration and synchronization between multiple threads and ensure data integrity and correct program execution. 8 9TaskPool is well-suited for individual, independent tasks. Therefore, it is recommended for scenarios where synchronous tasks are relatively independent, such as a series of static methods or methods implemented using a singleton pattern. Conversely, if synchronous tasks are interdependent, Worker is the better choice, especially when methods rely on class objects. 10 11 12## Using TaskPool for Independent Synchronous Tasks 13 14TaskPool is ideal for scheduling independent tasks or when a series of tasks is implemented as static methods. It is also suitable when unique handles or class objects can be constructed via a singleton pattern and used across different task threads. 15 16> **NOTE** 17> 18> Due to the memory isolation feature of the [actor model](multi-thread-concurrency-overview.md#actor-model) between threads, regular singletons cannot be shared across threads. This issue can be solved by exporting singletons through sendable modules. 19 201. Define a concurrent function to implement service logic. 21 222. Create a [task](../reference/apis-arkts/js-apis-taskpool.md#task), and execute the task using 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 logic uses TaskPool to call related synchronous methods. First, define the concurrent function **taskpoolFunc**, which must be decorated with [@Concurrent](taskpool-introduction.md#concurrent-decorator). Then, define the function **mainFunc**, which creates tasks, executes them, and performs operations on the results returned by the tasks. 27 28 29```ts 30// Index.ets code 31import { taskpool} from '@kit.ArkTS'; 32 33// Step 1: Define a concurrent function to implement service logic. 34@Concurrent 35async function taskpoolFunc(num: number): Promise<number> { 36 // Implement the corresponding functionality 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 result returned by the task. 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 for Interdependent Synchronous Tasks 76 77When a series of synchronous tasks needs to be scheduled using the same handle, or when they depend on a specific class object that cannot be shared across different task pools, Worker is the appropriate choice. 78 791. Create a Worker object in the UI main thread and receive messages from the Worker thread. DevEco Studio supports generation of Worker templates with a single click. In the corresponding {moduleName} directory, right-click anywhere and choose **New > Worker** to automatically generate the Worker template files 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 results from the Worker thread. 100 } 101 w.onAllErrors = (): void => { 102 // Receive error messages from 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 // Destroy the thread based on actual service requirements. 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' // Import the 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