sync-task-development.md 4.7 KB
Newer Older
G
ge-yafang 已提交
1 2 3 4 5 6
# 同步任务开发指导


同步任务是指在多个线程之间协调执行的任务,其目的是确保多个任务按照一定的顺序和规则执行,例如使用锁来防止数据竞争。


G
ge-yafang 已提交
7 8 9
同步任务的实现需要考虑多个线程之间的协作和同步,以确保数据的正确性和程序的正确执行。

由于TaskPool偏向于单个独立的任务,因此当各个同步任务之间相对独立时推荐使用TaskPool,例如一系列导入的静态方法,或者单例实现的方法。如果同步任务之间有关联性,则需要使用Worker,例如无法单例创建的类对象实现的方法。
G
ge-yafang 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27


## 使用TaskPool处理同步任务

当调度独立的同步任务,或者一系列同步任务为静态方法实现,或者可以通过单例构造唯一的句柄或类对象,可在不同任务池之间使用时,推荐使用TaskPool。

1. 定义并发函数,内部调用同步方法。

2. 创建任务,并通过TaskPool执行,再对异步结果进行操作。创建[Task](../reference/apis/js-apis-taskpool.md#task),并通过[execute()](../reference/apis/js-apis-taskpool.md#taskpoolexecute-1)接口执行同步任务。

3. 执行并发操作。

模拟一个包含同步调用的单实例类。


```ts
// Handle.ts 代码
export default class Handle {
28
  static getInstance(): void {
G
ge-yafang 已提交
29 30 31
    // 返回单例对象
  }

32
  static syncGet(): void {
G
ge-yafang 已提交
33 34 35
    // 同步Get方法
  }

36
  static syncSet(num: number): void {
G
ge-yafang 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    // 同步Set方法
  }
}
```

业务使用TaskPool调用相关同步方法的代码。


```ts
// Index.ets代码
import taskpool from '@ohos.taskpool';
import Handle from './Handle'; // 返回静态句柄

// 步骤1: 定义并发函数,内部调用同步方法
@Concurrent
52
function func(num: number): boolean {
G
ge-yafang 已提交
53 54 55 56 57 58 59 60
  // 调用静态类对象中实现的同步等待调用
  Handle.syncSet(num);
  // 或者调用单例对象中实现的同步等待调用
  Handle.getInstance().syncGet();
  return true;
}

// 步骤2: 创建任务并执行
61
async function asyncGet(): Promise<void> {
G
ge-yafang 已提交
62
  // 创建task并传入函数func
63 64 65
  let task: taskpool.Task = new taskpool.Task(func, 1);
  // 执行task任务并对同步逻辑后的结果进行操作
  console.info(String(await taskpool.execute(task)));
G
ge-yafang 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(() => {
            // 步骤3: 执行并发操作
            asyncGet();
          })
      }
      .width('100%')
      .height('100%')
    }
  }
}
```


## 使用Worker处理关联的同步任务

当一系列同步任务需要使用同一个句柄调度,或者需要依赖某个类对象调度,无法在不同任务池之间共享时,需要使用Worker。

1. 在主线程中创建Worker对象,同时接收Worker线程发送回来的消息。
97

G
ge-yafang 已提交
98 99
   ```js
   import worker from '@ohos.worker';
100

G
ge-yafang 已提交
101 102 103 104
   @Entry
   @Component
   struct Index {
     @State message: string = 'Hello World';
105

G
ge-yafang 已提交
106 107 108 109 110 111 112
     build() {
       Row() {
         Column() {
           Text(this.message)
             .fontSize(50)
             .fontWeight(FontWeight.Bold)
             .onClick(() => {
113
               let w: worker.ThreadWorker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
G
ge-yafang 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
               w.onmessage = function (d) {
                 // 接收Worker子线程的结果
               }
               w.onerror = function (d) {
                 // 接收Worker子线程的错误信息
               }
               // 向Worker子线程发送Set消息
               w.postMessage({'type': 0, 'data': 'data'})
               // 向Worker子线程发送Get消息
               w.postMessage({'type': 1})
               // 销毁线程
               w.terminate()
             })
         }
         .width('100%')
       }
       .height('100%')
     }
   }
   ```

2. 在Worker线程中绑定Worker对象,同时处理同步任务逻辑。
136

G
ge-yafang 已提交
137 138 139 140 141 142
   ```js
   // handle.ts代码
   export default class Handle {
     syncGet() {
       return;
     }
143

G
ge-yafang 已提交
144 145 146 147
     syncSet(num: number) {
       return;
     }
   }
148

G
ge-yafang 已提交
149 150 151
   // Worker.ts代码
   import worker, { ThreadWorkerGlobalScope, MessageEvents } from '@ohos.worker';
   import Handle from './handle.ts'  // 返回句柄
152

G
ge-yafang 已提交
153
   var workerPort : ThreadWorkerGlobalScope = worker.workerPort;
154

G
ge-yafang 已提交
155 156
   // 无法传输的句柄,所有操作依赖此句柄
   var handler = new Handle()
157

G
ge-yafang 已提交
158 159 160 161 162 163 164 165 166 167 168 169
   // Worker线程的onmessage逻辑
   workerPort.onmessage = function(e : MessageEvents) {
     switch (e.data.type) {
       case 0:
         handler.syncSet(e.data.data);
         workerPort.postMessage('success set');
       case 1:
         handler.syncGet();
         workerPort.postMessage('success get');
     }
   }
   ```