• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 同步任务开发指导 (TaskPool和Worker)
2
3
4同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。
5
6
7同步任务的实现需要考虑多个线程之间的协作和同步,以确保数据的正确性和程序的正确执行。
8
9由于TaskPool偏向于单个独立的任务,因此当各个同步任务之间相对独立时推荐使用TaskPool,例如一系列导入的静态方法,或者单例实现的方法。如果同步任务之间有关联性,则需要使用Worker,例如无法单例创建的类对象实现的方法。
10
11
12## 使用TaskPool处理同步任务
13
14当调度独立的任务,或者一系列任务为静态方法实现,或者可以通过单例构造唯一的句柄或类对象,可在不同任务线程之间使用时,推荐使用TaskPool。
15
161. 定义并发函数,内部调用同步方法。
17
182. 创建任务[Task](../reference/apis-arkts/js-apis-taskpool.md#task),通过[execute()](../reference/apis-arkts/js-apis-taskpool.md#taskpoolexecute-1)接口执行该任务,并对任务返回的结果进行操作。
19
203. 执行并发操作。
21
22模拟一个包含同步调用的单实例类。
23
24
25```ts
26// Handle.ts 代码
27export default class Handle {
28  static getInstance(): void {
29    // 返回单例对象
30  }
31
32  static syncGet(): void {
33    // 同步Get方法
34  }
35
36  static syncSet(num: number): number {
37    // 模拟同步步骤1
38    console.info("taskpool: this is 1st print!");
39    // 模拟同步步骤2
40    console.info("taskpool: this is 2nd print!");
41    return num++;
42  }
43}
44```
45
46
47业务使用TaskPool调用相关同步方法的代码。
48
49
50```ts
51// Index.ets代码
52import taskpool from '@ohos.taskpool';
53import Handle from './Handle'; // 返回静态句柄
54
55// 步骤1: 定义并发函数,内部调用同步方法
56@Concurrent
57function func(num: number): boolean {
58  // 调用静态类对象中实现的同步等待调用
59  Handle.syncSet(num);
60  return true;
61}
62
63// 步骤2: 创建任务并执行
64async function asyncGet(): Promise<void> {
65  // 创建task并传入函数func
66  let task: taskpool.Task = new taskpool.Task(func, 1);
67  // 执行task任务
68  let res: boolean = await taskpool.execute(task) as boolean;
69  // 打印任务结果
70  console.info("taskpool: task res is: " + res);
71}
72
73@Entry
74@Component
75struct Index {
76  @State message: string = 'Hello World';
77
78  build() {
79    Row() {
80      Column() {
81        Text(this.message)
82          .fontSize(50)
83          .fontWeight(FontWeight.Bold)
84          .onClick(() => {
85            // 步骤3: 执行并发操作
86            asyncGet();
87          })
88      }
89      .width('100%')
90      .height('100%')
91    }
92  }
93}
94```
95
96
97## 使用Worker处理关联的同步任务
98
99当一系列同步任务需要使用同一个句柄调度,或者需要依赖某个类对象调度,无法在不同任务池之间共享时,需要使用Worker。
100
1011. 在主线程中创建Worker对象,同时接收Worker线程发送回来的消息。
102
103    ```ts
104    import worker from '@ohos.worker';
105
106    @Entry
107    @Component
108    struct Index {
109      @State message: string = 'Hello World';
110
111      build() {
112        Row() {
113          Column() {
114            Text(this.message)
115              .fontSize(50)
116              .fontWeight(FontWeight.Bold)
117              .onClick(() => {
118                let w: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
119                w.onmessage = (): void => {
120                  // 接收Worker子线程的结果
121                }
122                w.onerror = (): void => {
123                  // 接收Worker子线程的错误信息
124                }
125                // 向Worker子线程发送Set消息
126                w.postMessage({'type': 0, 'data': 'data'})
127                // 向Worker子线程发送Get消息
128                w.postMessage({'type': 1})
129                // ...
130                // 根据实际业务,选择时机以销毁线程
131                w.terminate()
132              })
133          }
134          .width('100%')
135        }
136        .height('100%')
137      }
138    }
139    ```
140
141
1422. 在Worker线程中绑定Worker对象,同时处理同步任务逻辑。
143
144    ```ts
145    // handle.ts代码
146    export default class Handle {
147      syncGet() {
148        return;
149      }
150
151      syncSet(num: number) {
152        return;
153      }
154    }
155    ```
156
157    ```ts
158    // MyWorker.ts代码
159    import worker, { ThreadWorkerGlobalScope, MessageEvents } from '@ohos.worker';
160    import Handle from './handle'  // 返回句柄
161
162    let workerPort : ThreadWorkerGlobalScope = worker.workerPort;
163
164    // 无法传输的句柄,所有操作依赖此句柄
165    let handler: Handle = new Handle()
166
167    // Worker线程的onmessage逻辑
168    workerPort.onmessage = (e : MessageEvents): void => {
169     switch (e.data.type as number) {
170      case 0:
171       handler.syncSet(e.data.data);
172       workerPort.postMessage('success set');
173      case 1:
174       handler.syncGet();
175       workerPort.postMessage('success get');
176     }
177    }
178    ```
179