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