Worker向宿主线程进行消息插队通信

场景说明

在Worker多线程开发中,Worker线程通过postMessage向宿主线程(主线程或其他Worker线程)发送消息时,消息按照发送顺序依次排队处理。当宿主线程繁忙时,消息队列中可能积压大量待处理消息,导致某些需要及时处理的消息(如用户交互响应、关键状态更新等)无法被及时执行。

针对上述场景,从API版本26.0.0开始,ArkTS提供了postMessageAtFront接口,允许Worker线程向宿主线程发送插队消息,使消息插入到对应优先级消息队列的头部,从而被提前处理。

插队机制

使用示例

以下示例通过模拟宿主线程繁忙的场景,演示Worker线程如何通过postMessageAtFront()接口向宿主线程发送插队消息。

  1. 在宿主线程创建Worker对象,并发送、接收消息。

    此例中,可通过点击“触发消息发送”按钮,发送消息给Worker线程。

    import { MessageEvents, worker } from '@kit.ArkTS';
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
      @State workerObject: worker.ThreadWorker | null = null;
      aboutToAppear(): void {
        this.workerObject = new worker.ThreadWorker('entry/ets/workers/Worker.ets');
        this.workerObject.onmessage = (e: MessageEvents): void => {
          // 模拟耗时操作,每个接收到的消息处理100ms,让消息排队起来
          let start = new Date().getTime();
          while (new Date().getTime() - start < 100) {
            continue;
          }
          let res: string = e.data as string;
          console.info('result is: ' + JSON.stringify(res));
        }
      }
      build() {
        Row() {
          Column({space: 20}) {
            Text(this.message)
              .fontSize(50)
              .fontWeight(FontWeight.Bold)
            Button('触发消息发送')
              .fontSize(50)
              .onClick(()=>{
                if (this.workerObject != null) {
                  this.workerObject.postMessage('normal');
                }
              })
            Button('释放worker')
              .fontSize(50)
              .onClick(()=>{
                if (this.workerObject != null) {
                  this.workerObject.terminate();
                  this.workerObject = null;
                }
              })
          }
          .width('100%')
        }
        .height('100%')
      }
    }
  2. 在Worker线程中发送插队消息。

    Worker线程收到宿主线程发送的消息后,发送普通消息和插队消息。

    import { MessageEvents, ThreadWorkerGlobalScope, worker, Priority } from '@kit.ArkTS';
    
    const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
    
    workerPort.onmessage = (e: MessageEvents) => {
      // 发送多个消息,让消息排队起来
      for (let i = 0; i < 10; i++) {
        // 使用普通消息发送,按默认顺序排队处理
        workerPort.postMessage('normal message.');
      }
      // HIGH优先级:和普通消息相同优先级,插入到队列头部,让消息提前执行
      workerPort.postMessageAtFront?.('atFront high message', Priority.HIGH);
    }