【HarmonyOS Next】鴻蒙應用進程和線程詳解
一、前言
-
進程的定義:
進程是系統進行資源分配的基本單位,是操作系統結構的基礎。在鴻蒙系統中,一個應用下會有三類進程:
(1) 主進程,
(2) ExtensionAbility進程,同一種類型的ExtensionAbility會放在一個進程里。例如FromExtensionAbility,創建了兩個,也會在同一個進程里。【ExtensionAbility詳情參見官方鏈接:ExtensionAbility組件】
(3) WebView渲染進程,用于網頁容器渲染的進程。【這種設計提升了鴻蒙系統中arkWeb的網頁容器渲染能力】 -
線程的定義:
線程是操作系統進行運算調度的基本單位,是進程中的執行流,共享進程的資源。鴻蒙系統中,以主進程舉例,會有三種類型的線程:
(1)主線程
(2)TaskPool Worker線程
(3)Worker線程
后兩者用于創建多線程,TaskPool Worker主要用于處理輕量級的耗時任務。Worker用于偏重的耗時任務。
二、進程處理:
-
進程的創建:
如上圖所示,三方應用可以創建XXExtensionAbility的形式,增加應用內的進程。但是Webview渲染進程和主進程的是不能創建增加。 -
跨進程通信:
鴻蒙系統目前提供了兩種方式實現跨進程通信,公共事件和Emitter。這兩個方案外,startAbility也可傳遞一些信息。
公共事件主要是監聽系統的事件,分為系統公共事件和自定義事件。三方應用主要通過自定義事件來通信。
import { commonEventManager } from '@kit.BasicServicesKit';
import { BusinessError } from '@kit.BasicServicesKit';// 定義訂閱者,用于保存創建成功的訂閱者對象,后續使用其完成訂閱及退訂的動作
let subscriber: commonEventManager.CommonEventSubscriber;
// 訂閱者信息
let subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {events: ["event"]
};
// 創建訂閱者回調
function createCB(err: BusinessError, commonEventSubscriber: commonEventManager.CommonEventSubscriber) {if (err != null) {console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`);} else {console.info(`Succeeded in creating subscriber`);subscriber = commonEventSubscriber;}
}
// 創建訂閱者
commonEventManager.createSubscriber(subscribeInfo, createCB);
Emitter的使用類似于EventHub,只不過在這個基礎上,多了傳遞包裹的封裝,添加了優先級和序號。也新增了once,監聽一次的接口而已。
class Sample {constructor() {this.count = 100;}printCount() {console.info('Print count : ' + this.count);}count: number;
}let callback = (eventData: emitter.GenericEventData<Sample>): void => {let storage: Sample = eventData.data!;storage.printCount();
}
// 收到eventId為"eventId"的事件后執行回調函數
emitter.on("eventId", callback);
三、線程處理:
1.線程的創建和線程間通信:
如上所說,可以使用TaskPool Worker 和 Worker創建線程。并且配套會有雙向通信的接口。
需要注意的是前者有性能要求,太過于耗時的操作,例如超過三分鐘,就會無條件失敗,這種耗時任務就要使用后者Worker來實現。不過后者又因為消耗系統資源,一個應用只能創建八個。
TaskPool Worker:
printArgs(args: number): number {console.info("printArgs: " + args);return args;
}taskpool.execute(printArgs, 100).then((value: Object) => { // 100: test numberconsole.info("taskpool result: " + value);
});
function
Worker:
// Worker.ets
import { worker, MessageEvents, ErrorEvent } from '@kit.ArkTS';// 創建worker線程中與宿主線程通信的對象
const workerPort = worker.workerPort// worker線程接收宿主線程信息
workerPort.onmessage = (e: MessageEvents): void => {// data:宿主線程發送的信息let data: number = e.data;// 往收到的buffer里寫入數據const view = new Int8Array(data).fill(3);// worker線程向宿主線程發送信息workerPort.postMessage(view);
}// worker線程發生error的回調
workerPort.onerror = (err: ErrorEvent) => {console.log("worker.ets onerror" + err.message);
}// Index.ets
import { worker, MessageEvents, ErrorEvent } from '@kit.ArkTS';
struct Index { message: string = 'Hello World';build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {// 宿主線程中創建Worker對象const workerInstance = new worker.ThreadWorker("entry/ets/workers/Worker.ets");// 宿主線程向worker線程傳遞信息const buffer = new ArrayBuffer(8);workerInstance.postMessage(buffer, [buffer]);// 宿主線程接收worker線程信息workerInstance.onmessage = (e: MessageEvents): void => {// data:worker線程發送的信息let data: number = e.data;console.info("main thread data is " + data);// 銷毀Worker對象workerInstance.terminate();}// 在調用terminate后,執行onexitworkerInstance.onexit = (code) => {console.log("main thread terminate");}workerInstance.onerror = (err: ErrorEvent) => {console.log("main error message " + err.message);}})}.width('100%').height('100%')}}
}
2.線程內通信:
EventHub,GlobalThis,單例,AppStorage。都可實現線程內UI界面,UIAbility和業務類之間的通信。