• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
10
11
12## Using TaskPool for Independent Synchronous Tasks
13
14TaskPool is recommended in the following scenarios:
15
16- Tasks that are scheduled independently.
17
18- Tasks that are implemented using static methods.
19
20- Singleton handles or class objects used across threads.
21
22> **NOTE**
23>
24> 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.
25
261. Define a concurrent function to implement service logic.
27
282. 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.
29
303. Perform operations on the task result.
31
32In 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 processes the results returned by the tasks.
33
34
35```ts
36// Index.ets code
37import { taskpool} from '@kit.ArkTS';
38
39// Step 1: Define a concurrent function to implement service logic.
40@Concurrent
41async function taskpoolFunc(num: number): Promise<number> {
42  // Implement the corresponding functionality based on the service logic.
43  let tmpNum: number = num + 100;
44  return tmpNum;
45}
46
47async function mainFunc(): Promise<void> {
48  // Step 2: Create and execute a task.
49  let task1: taskpool.Task = new taskpool.Task(taskpoolFunc, 1);
50  let res1: number = await taskpool.execute(task1) as number;
51  let task2: taskpool.Task = new taskpool.Task(taskpoolFunc, res1);
52  let res2: number = await taskpool.execute(task2) as number;
53  // Step 3: Perform operations on the result returned by the task.
54  console.info("taskpool: task res1 is: " + res1);
55  console.info("taskpool: task res2 is: " + res2);
56}
57
58@Entry
59@Component
60struct Index {
61  @State message: string = 'Hello World';
62
63  build() {
64    Row() {
65      Column() {
66        Text(this.message)
67          .fontSize(50)
68          .fontWeight(FontWeight.Bold)
69          .onClick(async () => {
70            mainFunc();
71          })
72      }
73      .width('100%')
74      .height('100%')
75    }
76  }
77}
78```
79<!-- @[taskpool_handle_sync_task](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ApplicationMultithreadingDevelopment/ApplicationMultithreading/entry/src/main/ets/managers/SyncTaskDevelopment.ets) -->
80
81
82## Using Worker for Interdependent Synchronous Tasks
83
84When 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.
85
861. 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.
87
88    ```ts
89    // Index.ets
90    import { worker } from '@kit.ArkTS';
91
92    @Entry
93    @Component
94    struct Index {
95      @State message: string = 'Hello World';
96
97      build() {
98        Row() {
99          Column() {
100            Text(this.message)
101              .fontSize(50)
102              .fontWeight(FontWeight.Bold)
103              .onClick(() => {
104                let w: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
105                w.onmessage = (): void => {
106                  // Receive results from the Worker thread.
107                }
108                w.onAllErrors = (): void => {
109                  // Receive error messages from the Worker thread.
110                }
111                // Send a Set message to the Worker thread.
112                w.postMessage({'type': 0, 'data': 'data'})
113                // Send a Get message to the Worker thread.
114                w.postMessage({'type': 1})
115                // ...
116                // Destroy the thread based on actual service requirements.
117                w.terminate()
118              })
119          }
120          .width('100%')
121        }
122        .height('100%')
123      }
124    }
125    ```
126    <!-- @[worker_handle_associated_sync_task](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ApplicationMultithreadingDevelopment/ApplicationMultithreading/entry/src/main/ets/managers/SyncTaskDevelopment.ets) -->
127
128
1292. Bind the Worker object in the Worker thread and process the synchronous task logic.
130
131    ```ts
132    // handle.ts code
133    export default class Handle {
134      syncGet() {
135        return;
136      }
137
138      syncSet(num: number) {
139        return;
140      }
141    }
142    ```
143    <!-- @[worker_handle_associated_sync_task](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ApplicationMultithreadingDevelopment/ApplicationMultithreading/entry/src/main/ets/workers/handle.ts) -->
144
145    ```ts
146    // MyWorker.ts code
147    import { worker, ThreadWorkerGlobalScope, MessageEvents } from '@kit.ArkTS';
148    import Handle from './handle'  // Import the handle.
149
150    let workerPort : ThreadWorkerGlobalScope = worker.workerPort;
151
152    // Handle that cannot be transferred. All operations depend on this handle.
153    let handler: Handle = new Handle()
154
155    // onmessage() logic of the Worker thread.
156    workerPort.onmessage = (e : MessageEvents): void => {
157     switch (e.data.type as number) {
158      case 0:
159       handler.syncSet(e.data.data);
160       workerPort.postMessage('success set');
161       break;
162      case 1:
163       handler.syncGet();
164       workerPort.postMessage('success get');
165       break;
166     }
167    }
168    ```
169    <!-- @[worker_handle_associated_sync_task](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ApplicationMultithreadingDevelopment/ApplicationMultithreading/entry/src/main/ets/workers/MyWorker2.ts) -->
170