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
    // 同步Set方法
  }
}
```

42

G
ge-yafang 已提交
43 44 45 46 47 48 49 50 51 52
业务使用TaskPool调用相关同步方法的代码。


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

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

// 步骤2: 创建任务并执行
60
async function asyncGet(): Promise<void> {
G
ge-yafang 已提交
61
  // 创建task并传入函数func
62 63 64
  let task: taskpool.Task = new taskpool.Task(func, 1);
  // 执行task任务并对同步逻辑后的结果进行操作
  console.info(String(await taskpool.execute(task)));
G
ge-yafang 已提交
65 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
}

@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线程发送回来的消息。
96

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

134

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

137 138 139 140 141 142 143 144 145 146 147
    ```ts
    // handle.ts代码
    export default class Handle {
      syncGet() {
        return;
      }
    
      syncSet(num: number) {
        return;
      }
    }
148
    ```
149
    
150
    ```ts
151 152
    // Worker.ts代码
    import worker, { ThreadWorkerGlobalScope, MessageEvents } from '@ohos.worker';
153
    import Handle from './handle'  // 返回句柄
154
    
155
    let workerPort : ThreadWorkerGlobalScope = worker.workerPort;
156 157
    
    // 无法传输的句柄,所有操作依赖此句柄
158
    let handler: Handle = new Handle()
159 160 161 162 163 164 165 166 167 168
    
    // Worker线程的onmessage逻辑
    workerPort.onmessage = (e : MessageEvents): void => {
     switch (e.data.type as number) {
      case 0:
       handler.syncSet(e.data.data);
       workerPort.postMessage('success set');
      case 1:
       handler.syncGet();
       workerPort.postMessage('success get');
G
ge-yafang 已提交
169
     }
170 171
    }
    ```