HarmonyOS 鸿蒙Next 子线程共享@Sendable怎么用

发布于 1周前 作者 vueper 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 子线程共享@Sendable怎么用

我现在用子线程查询数据,我要把原有得数据传递到TaskTool任务里面但是我的class已经使用了注解@Observed  无法和@Sendable 共存,并且我的class里面有一个枚举,枚举又无法使用@Sendable 注解,导致我根本无法使用TaskTool  ,请问有没有更好的办法解决这个序列化的问题,


更多关于HarmonyOS 鸿蒙Next 子线程共享@Sendable怎么用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

@Sendable共享模块就单独用来处理ui线程和子线程数据,ui页面的数据单独用@Observed修饰。然后把枚举改为number来处理,做好映射。 这边有个用worker来实现ui和数据库之间的数据操作,可以看一下

Index.ets

import worker, { MessageEvents } from '@ohos.worker';

import { Student } from '../database/student';

const workerInstance = new worker.ThreadWorker("entry/ets/workers/Worker.ets");

let context = getContext()

let nameArr = ['jack','tom','anlay','jany','lili','Aaron','Ben','Brandon','Cody','Mason']

@Entry

@Component

struct Index {

  @State list: Student[] = [];

  aboutToAppear(): void {

    workerInstance.postMessage({code:99,data:context});

    workerInstance.onmessage = (e:MessageEvents):void=>{

      if(e.data.code == 101){

         this.list = e.data.data

      }

    }

  }

  build() {

    Row() {

      Column() {

        Row(){

          Button('建表')

            .onClick(() => {

              workerInstance.postMessage({code:1,data:context});

            })

          Button('插入数据')

            .onClick(() => {

              let student:Student = new Student()

              let index = Math.ceil(Math.random()*10)%10

              student.name = nameArr[index]

              student.age = Math.ceil(Math.random()*100)%18

              student.salary = 2000 + Math.ceil(Math.random()*10000)%10000

              workerInstance.postMessage({code:2,data:student});

            })

          Button('查询数据')

            .onClick(() => {

              workerInstance.postMessage({code:3,data:{}});

            })

        }

        .width('100%')

        .margin({top:10})

        .justifyContent(FlexAlign.SpaceAround)

        ForEach(this.list, (item: Student, index: number) => {

          ViewA({ student: item})

        })

      }

      .height('100%')

      .width('100%')

    }

  }

}

@Component

export struct ViewA {

  student: Student = new Student();

  build() {

    Row(){

      Text("姓名:"+this.student.name)

      Text("年龄:"+this.student.age.toString())

      Text("费用:"+this.student.salary.toString())

    }.width('100%').margin({top : 10 }).justifyContent(FlexAlign.SpaceEvenly)

  }

}

Worker.ets


import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS';

import Rdb from '../database/rdb'

import { Student } from '../database/student';

const workerPort: ThreadWorkerGlobalScope = worker.workerPort;

let rdbTest: Rdb;

workerPort.onmessage = async (e: MessageEvents) => {

  console.log('testtag onmessage' + JSON.stringify(e))

  if (e.data.code == 1) {

    rdbTest.CreateTable(); //建表

  } else if (e.data.code == 2) {

    let student = e.data.data as Student

    await rdbTest.InsertData(student.name, student.age, student.salary); //添加数据

    //添加新数据收立马查询,然后同时主线程

    let studentArr = await rdbTest.QueryDataArr();

    //将处理结果返回主线程

    workerPort.postMessage({code:101,data:studentArr})

  } else if (e.data.code == 3) {

    let studentArr = await rdbTest.QueryDataArr();

    //将处理结果返回主线程

    workerPort.postMessage({code:101,data:studentArr})

    } else {

    rdbTest = await new Rdb('Student.db', e.data.data) //创建数据库

  }

  console.log('testtag onmessage end')

}

workerPort.onmessageerror = (e: MessageEvents) => {

  console.log('testtag onmessageerror' + e)

}

workerPort.onerror = (e: ErrorEvent) => {

}

Student.ets


export class Student {

  id: number = 0

  name: string = ''

  age: number = 1

  salary:number = 0

}

rdb.ets


import relationalStore from '@ohos.data.relationalStore';

import { BusinessError, Callback } from '@ohos.base';

import { ValuesBucket } from '@ohos.data.ValuesBucket';

import { Student } from './student';

export default class Rdb {

  rdbStore?: relationalStore.RdbStore;

  constructor(storeName: string, context: Context) {

    // 数据库配置

    const STORE_CONFIG: relationalStore.StoreConfig = {

    name: storeName, securityLevel: relationalStore.SecurityLevel.S1,

    };

    // 获取数据库Store

    relationalStore.getRdbStore(context, STORE_CONFIG, (err: BusinessError, rdbStore: relationalStore.RdbStore) => {

      this.rdbStore = rdbStore;

      if (err) {

        console.error(`Get RdbStore failed, code is ${err.code},message is ${err.message}`);

        return;

       }

       console.info(`Get ${storeName} RdbStore successfully.`);

    })

  }

CreateTable() {

  const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS STUDENT (ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,AGE INTEGER,SALARY INTEGER)';

  if (this.rdbStore) {

    this.rdbStore.executeSql(SQL_CREATE_TABLE); console.info(`CreateTable successfully.`);

  }

}

InsertData(name: string, age: number, salary: number) {

  // 插入数据

  const valueBucket: ValuesBucket = { 'NAME': name, 'AGE': age, 'SALARY': salary };

  setTimeout(() => {

    if (this.rdbStore) {

      this.rdbStore.insert('STUDENT', valueBucket, (err, rowId) => {

        if (err) {

          console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);

          return;

        }

        console.info(`Succeeded in inserting data. rowId:${rowId}`);

      })

    }

  }, 10)

}

async InsertAsync(name: string, age: number, salary: number) {

  let start = Date.now(); const valueBucket:

    ValuesBucket = { 'NAME': name, 'AGE': age, 'SALARY': salary };

  /* while (Date.now() - start <1000) { continue; } console.log('延时结束');*/

  if (this.rdbStore) {

    await this.rdbStore.insert('STUDENT', valueBucket, (err, rowId) => {

      if (err) {

        console.error(`Failed to insert data. Code:${err.code}, message:${err.message}`);

        return;

  }

  console.info(`Succeeded in inserting data. rowId:${rowId}`);

})

}

}

DeleteData() {

  let predicates = new relationalStore.RdbPredicates("STUDENT"); predicates.equalTo("NAME", "Lisa");

  if (this.rdbStore != undefined) {

    (this.rdbStore as relationalStore.RdbStore).delete(predicates, (err, rows) => {

      if (err) { console.error(`Delete failed, code is ${err.code},message is ${err.message}`);

    return;

  }

  console.info(`Delete rows: ${rows}`);

})

}

}

queryData() {

  let predicates = new relationalStore.RdbPredicates("STUDENT") .notEqualTo('name', 'li') .orderByAsc('age') .orderByAsc('salary')

  if (this.rdbStore) {

    this.rdbStore.query(predicates, ["ID", 'NAME', 'AGE', 'SALARY'], (err, resultSet) => {

      if (err) {

        console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);

        return;

  }

  console.info(`ResultSet column names: ${resultSet.columnNames}, row count: ${resultSet.rowCount}`);

  if (resultSet.rowCount == -1) {

    console.info("rowCount=-1")

  }

  // resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。

  while (resultSet.goToNextRow()) {

    const id = resultSet.getLong(resultSet.getColumnIndex("ID"));

    const name = resultSet.getString(resultSet.getColumnIndex("NAME"));

    const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));

    const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

    console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}`);

}

// 释放数据集的内存

  resultSet.close();

})

}

}

querySyncData() {

  let predicates = new relationalStore.RdbPredicates("STUDENT") .notEqualTo('name', 'li') .orderByAsc('age') .orderByAsc('salary')

  try {

    if (this.rdbStore) {

      let resultSet = this.rdbStore.querySync(predicates, ["ID", 'NAME', 'AGE', 'SALARY']);

      console.info(`ResultSet column names: ${resultSet.columnNames}, row count: ${resultSet.rowCount}`);

      while (resultSet.goToNextRow()) {

        const id = resultSet.getLong(resultSet.getColumnIndex("ID"));

        const name = resultSet.getString(resultSet.getColumnIndex("NAME"));

        const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));

        const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

        console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}`);

}

// 释放数据集的内存

  resultSet.close();

}

} catch (err) {

  console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);

  return;

}

}

UpdateData(name: string, age: number, salary: number) {

  const valueBucket: ValuesBucket = { 'NAME': name, 'AGE': age, 'SALARY': salary };

  let predicates = new relationalStore.RdbPredicates("EMPLOYEE");

  predicates.equalTo("NAME", "Lisa");

  if (this.rdbStore != undefined) {

    (this.rdbStore as relationalStore.RdbStore).update(valueBucket, predicates, relationalStore.ConflictResolution.ON_CONFLICT_REPLACE, (err, rows) => {

      if (err) {

        console.error(`Updated failed, code is ${err.code},message is ${err.message}`);

        return;

  }

  console.info(`Updated row count: ${rows}`);

})

}

}

  QueryData(callback: Callback<string>) {

    // 配置谓词

    let predicates = new relationalStore.RdbPredicates("STUDENT");

    let jsonData: Array<ValuesBucket> = new Array<ValuesBucket>()

    if (this.rdbStore) {

      this.rdbStore.query(predicates, ["ID", 'NAME', 'AGE', 'SALARY'], (err, resultSet) => {

        if (err) {

          console.error(`Failed to query data. Code:${err.code}, message:${err.message}`);

          return;

        }

      console.info(`ResultSet column names: ${resultSet.columnNames}, row count: ${resultSet.rowCount}`);

      if (resultSet.rowCount == -1) {

        console.info("rowCount=-1")

      }

      // resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。

      while (resultSet.goToNextRow()) {

        const id = resultSet.getLong(resultSet.getColumnIndex("ID"));

        const name = resultSet.getString(resultSet.getColumnIndex("NAME"));

        const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));

        const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

        console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}`);

        const valueBucket: ValuesBucket = { 'ID': id, 'NAME': name, 'AGE': age, 'SALARY': salary};

        jsonData.push(valueBucket)

      }

        // 释放数据集的内存

     resultSet.close();

        // console.info("JSON: " + JSON.stringify(jsonData)) callback(JSON.stringify(jsonData))

    })

   }

  }

  async QueryDataArr(): Promise<Student[]> {

    // 配置谓词

    let predicates = new relationalStore.RdbPredicates("STUDENT");

    let rdbData: Array<Student> = new Array<Student>()

    if (this.rdbStore) {

      let resultSet = this.rdbStore.querySync(predicates, ["ID", 'NAME', 'AGE', 'SALARY'])

      while (resultSet.goToNextRow()) {

        const id = resultSet.getLong(resultSet.getColumnIndex("ID"));

        const name = resultSet.getString(resultSet.getColumnIndex("NAME"));

        const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));

        const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

        console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}`);

        const valueBucket: Student = new Student();

        valueBucket.id = id

        valueBucket.name = name

        valueBucket.age = age

        valueBucket.salary = salary

        rdbData.push(valueBucket)

      }

      // 释放数据集的内存

      resultSet.close();

      // console.info("JSON: " + JSON.stringify(jsonData)) callback(JSON.stringify(jsonData))

    }

    return rdbData

  }

  queryKeySync() {

    let predicates = new relationalStore.RdbPredicates("STUDENT");

    predicates.equalTo("NAME", "Lisa");

    if (this.rdbStore != undefined) {

      try {

        let resultSet: relationalStore.ResultSet = (this.rdbStore as relationalStore.RdbStore).querySync(predicates, ["ID", "NAME", "AGE", "SALARY"]);

        console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`);

        // resultSet是一个数据集合的游标,默认指向第-1个记录,有效的数据从0开始。

        while (resultSet.goToNextRow()) {

          const id = resultSet.getLong(resultSet.getColumnIndex("ID"));

          const name = resultSet.getString(resultSet.getColumnIndex("NAME"));

          const age = resultSet.getLong(resultSet.getColumnIndex("AGE"));

          const salary = resultSet.getDouble(resultSet.getColumnIndex("SALARY"));

          console.info(`id=${id}, name=${name}, age=${age}, salary=${salary}`);

        }

        // 释放数据集的内存

        resultSet.close();

      } catch (err) {

      console.error(`Query failed, code is ${err.code},message is ${err.message}`);

      }

    }

  }

}

更多关于HarmonyOS 鸿蒙Next 子线程共享@Sendable怎么用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙系统中,@Sendable 关键字主要用于确保闭包(Closure)或函数在并发环境中安全地传递和调用。在鸿蒙的多线程编程中,若想在子线程中安全地共享数据或调用函数,可以遵循以下使用方式:

@Sendable 通常与 @MainActor@Actor 等并发上下文标记一起使用,来明确闭包的并发安全性。但在鸿蒙系统中,具体的语法和标记可能有所不同,通常通过特定的API或框架来管理并发。

对于鸿蒙Next版本,如果你需要在子线程中共享数据,应使用鸿蒙提供的并发处理机制,如任务调度器(Task Dispatcher)或其他线程同步机制。@Sendable 闭包可以通过这些机制安全地在不同线程间传递。

示例代码片段(假设鸿蒙提供了类似Swift的语法支持,实际需参考鸿蒙API文档):

// 假设有一个函数需要在子线程中执行,并接收一个@Sendable闭包
func performInBackground(task: @escaping @Sendable () -> Void) {
    // 鸿蒙的线程或任务调度代码
}

// 创建一个@Sendable闭包
let myTask: @Sendable () -> Void = {
    // 执行任务
}

// 在子线程中执行
performInBackground(task: myTask)

如果问题依旧没法解决请联系官网客服, 官网地址是:https://www.itying.com/category-93-b0.html

回到顶部