HarmonyOS鸿蒙Next中使用TaskPool进行关系型数据库操作遇到的问题

HarmonyOS鸿蒙Next中使用TaskPool进行关系型数据库操作遇到的问题 1.不能通过@Concurrent修饰的函数将Context传入,显示Parameter error.Illegal context.

2.在主线程初始化数据库之后,将获取数据库数据接口进入taskpool,不能够访问数据,显示RDB store not initialized。

可是根据文档 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/batch-database-operations-guide#使用sendable进行大容量数据库操作 ,确实就可以通过taskpool操作数据库呢。

求大神指点。。。。。。挺着急的–!


更多关于HarmonyOS鸿蒙Next中使用TaskPool进行关系型数据库操作遇到的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

开发者您好,根据官网提供的demo:使用TaskPool进行频繁数据库操作,并没有复现您如上的两个问题,麻烦您提供如下信息吧:

1、复现代码(如最小复现demo);

2、版本信息(如:开发工具、手机系统版本信息);

更多关于HarmonyOS鸿蒙Next中使用TaskPool进行关系型数据库操作遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


大神您好:我现在使用的开发工具为:devecostudio/5.0.0(12),手机系统版本为Mate 60 pro 6.0.0.130

demo如下:

//ConcurrentFunctions

// ConcurrentFunctions
import { DownloadDatabaseManager, DownloadState } from '../manager/DownloadDatabaseManager';
import { DownloadInfo } from '../model/DownloadInfo';
import { common } from '[@kit](/user/kit).AbilityKit';

/**
 * 初始化数据库
 */
@Concurrent
export async function initDatabaseConcurrent(context: common.UIAbilityContext): Promise<boolean> {
  try {
    const dbManager = DownloadDatabaseManager.getInstance();
    const result = await dbManager.initDatabase(context);
    return result; // 直接返回 boolean
  } catch (error) {
    console.error('initDatabaseConcurrent error:', error);
    return false;
  }
}


/**
 * 获取所有下载信息
 */
@Concurrent
export async function getAllDownloadInfoConcurrent(): Promise<DownloadState> {
  try {
    const dbManager = DownloadDatabaseManager.getInstance();
    const result = await dbManager.getDownloadData();
    return result;
  } catch (error) {
    console.error('getAllDownloadInfoConcurrent error:', error);
    return {
      downloading: [],
      downloaded: []
    };
  }
}

/**
 * 获取所有下载信息
 */
@Concurrent
export async function batchSaveDownloadInfoConcurrent(validInfos: DownloadInfo[]): Promise<string[]> {
  try {
    const dbManager = DownloadDatabaseManager.getInstance();
    const result = await dbManager.batchSaveDownloadInfo(validInfos);
    return result
  } catch (error) {
    console.error('batchSaveDownloadInfoConcurrent error:', error);
    return []
  }
}

//DownloadDatabaseManager

import { relationalStore } from '[@kit](/user/kit).ArkData';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
import { bundleManager } from '[@kit](/user/kit).AbilityKit';
import { common } from '[@kit](/user/kit).AbilityKit';
import { DatabaseConstants } from '../util/DatabaseConstants';
import { DownloadInfo } from '../model/DownloadInfo';
import { logger } from '../util/DownloadLogger';

export class DownloadState {
  downloading: DownloadInfo[] = [];
  downloaded: DownloadInfo[] = [];
}

const TAG: string = 'DownloadDatabaseManager';

/**
 * 数据库版本常量 - 统一使用 DatabaseConstants 中的定义
 */
const DATABASE_VERSION = DatabaseConstants.DATABASE_VERSION;
const DATABASE_NAME = DatabaseConstants.DATABASE_NAME;
export class DownloadDatabaseManager {
  private static sInstance: DownloadDatabaseManager | null = null;
  private rdbStore: relationalStore.RdbStore | null = null;
  private isInitialized: boolean = false;
  private currentVersion: number = 0; // 当前数据库版本

  public static getInstance(): DownloadDatabaseManager {
    if (DownloadDatabaseManager.sInstance == null) {
      DownloadDatabaseManager.sInstance = new DownloadDatabaseManager();
    }
    return DownloadDatabaseManager.sInstance;
  }

  /**
   * 初始化数据库
   */
  public async initDatabase(context: common.UIAbilityContext): Promise<boolean> {
    if (this.isInitialized) {
      return true;
    }

    try {
      const STORE_CONFIG: relationalStore.StoreConfig = {
        name: DATABASE_NAME,
        securityLevel: relationalStore.SecurityLevel.S1
      };

      this.rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);

      // 获取当前数据库版本
      const oldVersion = await this.getDatabaseVersion();
      this.currentVersion = oldVersion;

      logger.info(TAG, `Database version: old=${oldVersion}, new=${DATABASE_VERSION}`);

      // 检查版本并执行相应操作
      if (oldVersion === 0) {
        // 首次创建数据库
        logger.info(TAG, 'Creating database tables for the first time');
        await this.createTable();
        await this.setDatabaseVersion(DATABASE_VERSION);
      } else if (oldVersion < DATABASE_VERSION) {
        // 需要升级
        logger.info(TAG, `Database needs upgrade from version ${oldVersion} to ${DATABASE_VERSION}`);
        await this.onUpgrade(oldVersion, DATABASE_VERSION);
      } else if (oldVersion > DATABASE_VERSION) {
        // 版本降级 - 数据库版本高于应用版本
        logger.warn(TAG, `Database version ${oldVersion} is higher than app version ${DATABASE_VERSION}`);
        throw new Error(`Database version ${oldVersion} is not compatible with app version ${DATABASE_VERSION}. Please upgrade the app.`);
      } else {
        // 版本一致,无需操作
        logger.info(TAG, 'Database version is up to date');
      }

      this.currentVersion = DATABASE_VERSION;
      this.isInitialized = true;
      logger.info(TAG, 'Database initialized successfully');
      return true;
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      logger.error(TAG, `Failed to initialize database: ${err.code} - ${err.message}`);
      return false;
    }
  }

  /**
   * 同步设置数据库版本
   */
  private setDatabaseVersionSync(version: number): void {
    if (!this.rdbStore) {
      return;
    }

    try {
      // 创建版本表(支持历史记录)
      const createTableSql = `
        CREATE TABLE IF NOT EXISTS db_version (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          version INTEGER NOT NULL,
          upgrade_time INTEGER NOT NULL,
          app_version TEXT
        )
      `;
      this.rdbStore.executeSync(createTableSql);

      // 插入新版本记录(保留历史)
      const upgradeTime = Date.now();
      const appVersion = this.getAppVersion();
      const insertSql = `
        INSERT INTO db_version (version, upgrade_time, app_version)
        VALUES (${version}, ${upgradeTime}, '${appVersion}')
      `;
      this.rdbStore.executeSync(insertSql);

      logger.info(TAG, `Database version set to ${version}, app version: ${appVersion} (sync)`);
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      logger.error(TAG, `Failed to set database version (sync): ${err.message}`);
      if (error instanceof Error) {
        throw error;
      } else {
        throw new Error(String(error));
      }
    }
  }

  /**
   * 同步创建完整的下载信息表
   */
  private createTableSync(): void {
    if (!this.rdbStore) {
      throw new Error('RDB store not initialized');
    }

    const CREATE_TABLE_SQL: string = `
      CREATE TABLE IF NOT EXISTS ${DatabaseConstants.TABLE_DOWNLOAD_INFO} (
        ${DatabaseConstants.COLUMN_ID} INTEGER PRIMARY KEY AUTOINCREMENT,
        ${DatabaseConstants.COLUMN_VIDEOID} TEXT NOT NULL UNIQUE,
        ${DatabaseConstants.COLUMN_TITLE} TEXT,
        ${DatabaseConstants.COLUMN_FORMAT} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_LANGUAGE} TEXT,
        ${DatabaseConstants.COLUMN_SHOWID} TEXT,
        ${DatabaseConstants.COLUMN_SHOWNAME} TEXT,
        ${DatabaseConstants.COLUMN_SHOW_VIDEOSEQ} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SHOWEPISODE_TOTAL} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_CATS} TEXT,
        ${DatabaseConstants.COLUMN_SECONDS} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEGS_SECONDS} TEXT,
        ${DatabaseConstants.COLUMN_STATE} INTEGER DEFAULT -1,
        ${DatabaseConstants.COLUMN_IS_PANORAMA} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_VIDEO_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_DRM_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_STREAM_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_STREAM_TOKEN} TEXT,
        ${DatabaseConstants.COLUMN_FILE_FORMAT} TEXT,
        ${DatabaseConstants.COLUMN_M3U8_URL} TEXT,
        ${DatabaseConstants.COLUMN_M3U8_FILE_ID} TEXT,
        ${DatabaseConstants.COLUMN_LICENSE_NUM} TEXT,
        ${DatabaseConstants.COLUMN_YOUKU_REGISTER_NUM} TEXT,
        ${DatabaseConstants.COLUMN_PAY_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_EXTRA_INFO} TEXT,
        ${DatabaseConstants.COLUMN_DOWNLOAD_TYPE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SAVE_ROOT_PATH} TEXT,
        ${DatabaseConstants.COLUMN_PCDN_REPAIRED} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_TASK_ID} TEXT,
        ${DatabaseConstants.COLUMN_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_DOWNLOADED_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_CREATE_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_CAN_PLAY} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_DOWNLOADED_SECONDS} REAL DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEG_COUNT} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEG_ID} INTEGER DEFAULT 1,
        ${DatabaseConstants.COLUMN_SEG_DOWNLOADED_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEGS_SIZE} TEXT,
        ${DatabaseConstants.COLUMN_TOKEN} TEXT,
        ${DatabaseConstants.COLUMN_OIP} TEXT,
        ${DatabaseConstants.COLUMN_SID} TEXT,
        ${DatabaseConstants.COLUMN_THREAD_NUM} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_PLAY_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_LAST_PLAY_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IMG_URL} TEXT,
        ${DatabaseConstants.COLUMN_START_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_GET_URL_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_FINISH_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_LAST_UPDATE_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_EXCEPTION_ID} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_PROGRESS} REAL DEFAULT 0,
        ${DatabaseConstants.COLUMN_POINTS} TEXT,
        ${DatabaseConstants.COLUMN_PREVIEW} TEXT,
        ${DatabaseConstants.COLUMN_IS_SHOW_WATERMARK} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_EXCLUSIVE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_SUBTITLES_DOWNLOAD_FINISHED} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_PREVIEW_DOWNLOAD_FINISHED} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_VIDEO_THUMB_DOWNLOAD_FINISHED} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_ENCRYPTION} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_VERSION_CODE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_VERSION_NAME} TEXT,
        ${DatabaseConstants.COLUMN_IS_VERTICAL_VIDEO} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SHOW_SUBTITLE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_EXPOSURE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_PUSH_DOWNLOAD} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_VIDEO_DOWNLOAD_PASSWORD} TEXT,
        ${DatabaseConstants.COLUMN_SAVE_PATH} TEXT NOT NULL,
        ${DatabaseConstants.COLUMN_RETRY} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_IS_THUMBNAIL_DOWNLOADING} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_HEADER_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SPEED} TEXT,
        ${DatabaseConstants.COLUMN_SUBTITLES_JSON} TEXT,
        ${DatabaseConstants.COLUMN_AD} TEXT,
        ${DatabaseConstants.COLUMN_STREAM} TEXT,
        ${DatabaseConstants.COLUMN_INTELLIGENT_FOLDER} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_INTELLIGENT_RESTART_FROM_USER} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_EXTRA_INFO_MEM} TEXT,
        ${DatabaseConstants.COLUMN_SEG_INFOS} TEXT,
        ${DatabaseConstants.COLUMN_IS_DELETED} INTEGER DEFAULT 0
      )
    `;

    this.rdbStore.executeSync(CREATE_TABLE_SQL);

    // 创建索引
    const INDEXES: string[] = [
      `CREATE INDEX IF NOT EXISTS idx_videoid ON ${DatabaseConstants.TABLE_DOWNLOAD_INFO}(${DatabaseConstants.COLUMN_VIDEOID})`,
      `CREATE INDEX IF NOT EXISTS idx_state ON ${DatabaseConstants.TABLE_DOWNLOAD_INFO}(${DatabaseConstants.COLUMN_STATE})`,
      `CREATE INDEX IF NOT EXISTS idx_showid ON ${DatabaseConstants.TABLE_DOWNLOAD_INFO}(${DatabaseConstants.COLUMN_SHOWID})`,
      `CREATE INDEX IF NOT EXISTS idx_show_videoseq ON ${DatabaseConstants.TABLE_DOWNLOAD_INFO}(${DatabaseConstants.COLUMN_SHOW_VIDEOSEQ})`,
      `CREATE INDEX IF NOT EXISTS idx_create_time ON ${DatabaseConstants.TABLE_DOWNLOAD_INFO}(${DatabaseConstants.COLUMN_CREATE_TIME})`
    ];

    for (const indexSql of INDEXES) {
      try {
        this.rdbStore.executeSync(indexSql);
      } catch (error) {
        logger.warn(TAG, `Failed to create index (sync): ${error}`);
      }
    }

    logger.info(TAG, 'Database table and indexes created successfully (sync)');
  }

  /**
   * 同步数据库升级处理
   *
   * [@param](/user/param) oldVersion 旧版本号
   * [@param](/user/param) newVersion 新版本号
   */
  private onUpgradeSync(oldVersion: number, newVersion: number): void {
    if (!this.rdbStore) {
      throw new Error('RDB store not initialized');
    }

    logger.info(TAG, `Starting database upgrade from version ${oldVersion} to ${newVersion} (sync)`);

    try {
      // 开启事务
      this.rdbStore.beginTransaction();

      // 增量升级:从旧版本逐步升级到新版本
      let currentVersion = oldVersion;

      // 版本 0 -> 1: 创建初始表结构
      if (currentVersion < 1) {
        logger.info(TAG, 'Upgrading to version 1: Creating initial tables (sync)');
        this.createTableSync();
        currentVersion = 1;
      }

      // 更新版本号
      this.setDatabaseVersionSync(newVersion);

      // 提交事务
      this.rdbStore.commit();

      logger.info(TAG, `Database upgrade completed successfully to version ${newVersion} (sync)`);
    } catch (error) {
      // 升级失败,回滚事务
      this.rdbStore.rollBack();
      const err: BusinessError = error as BusinessError;
      logger.error(TAG, `Database upgrade failed (sync): ${err.message}`);
      throw new Error(`Database upgrade failed from version ${oldVersion} to ${newVersion}: ${err.message}`);
    }
  }

  /**
   * 创建完整的下载信息表
   */
  private async createTable(): Promise<void> {
    if (!this.rdbStore) {
      throw new Error('RDB store not initialized');
    }

    const CREATE_TABLE_SQL: string = `
      CREATE TABLE IF NOT EXISTS ${DatabaseConstants.TABLE_DOWNLOAD_INFO} (
        ${DatabaseConstants.COLUMN_ID} INTEGER PRIMARY KEY AUTOINCREMENT,
        ${DatabaseConstants.COLUMN_VIDEOID} TEXT NOT NULL UNIQUE,
        ${DatabaseConstants.COLUMN_TITLE} TEXT,
        ${DatabaseConstants.COLUMN_FORMAT} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_LANGUAGE} TEXT,
        ${DatabaseConstants.COLUMN_SHOWID} TEXT,
        ${DatabaseConstants.COLUMN_SHOWNAME} TEXT,
        ${DatabaseConstants.COLUMN_SHOW_VIDEOSEQ} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SHOWEPISODE_TOTAL} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_CATS} TEXT,
        ${DatabaseConstants.COLUMN_SECONDS} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEGS_SECONDS} TEXT,
        ${DatabaseConstants.COLUMN_STATE} INTEGER DEFAULT -1,
        ${DatabaseConstants.COLUMN_IS_PANORAMA} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_VIDEO_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_DRM_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_STREAM_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_STREAM_TOKEN} TEXT,
        ${DatabaseConstants.COLUMN_FILE_FORMAT} TEXT,
        ${DatabaseConstants.COLUMN_M3U8_URL} TEXT,
        ${DatabaseConstants.COLUMN_M3U8_FILE_ID} TEXT,
        ${DatabaseConstants.COLUMN_LICENSE_NUM} TEXT,
        ${DatabaseConstants.COLUMN_YOUKU_REGISTER_NUM} TEXT,
        ${DatabaseConstants.COLUMN_PAY_TYPE} TEXT,
        ${DatabaseConstants.COLUMN_EXTRA_INFO} TEXT,
        ${DatabaseConstants.COLUMN_DOWNLOAD_TYPE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SAVE_ROOT_PATH} TEXT,
        ${DatabaseConstants.COLUMN_PCDN_REPAIRED} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_TASK_ID} TEXT,
        ${DatabaseConstants.COLUMN_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_DOWNLOADED_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_CREATE_TIME} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_CAN_PLAY} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_DOWNLOADED_SECONDS} REAL DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEG_COUNT} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEG_ID} INTEGER DEFAULT 1,
        ${DatabaseConstants.COLUMN_SEG_DOWNLOADED_SIZE} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_SEGS_SIZE} TEXT,
        ${DatabaseConstants.COLUMN_TOKEN} TEXT,
        ${DatabaseConstants.COLUMN_OIP} TEXT,
        ${DatabaseConstants.COLUMN_SID} TEXT,
        ${DatabaseConstants.COLUMN_THREAD_NUM} INTEGER DEFAULT 0,
        ${DatabaseConstants.COLUMN_PLAY_TIME} INTEGER DEFAULT 0,
        ${

大神,还有个问题要请教一下您,taskpool子线程可以直接操作HashMap吗,我们这边也出现过这样的提示,说不可以操作HashMap这种复杂数据类型

在HarmonyOS Next中,TaskPool不支持直接操作关系型数据库。关系型数据库操作需在主线程或使用特定数据库API的异步方法进行。TaskPool适用于CPU密集型任务,如数据处理,不涉及UI或数据库访问。若需异步执行数据库操作,应使用数据库提供的异步接口或通过Worker线程处理。

根据你的描述,这是HarmonyOS Next中TaskPool与关系型数据库(RDB)交互的两个典型限制。我来为你解释原因和解决方案:

1. 关于@Concurrent函数无法传入Context: 这是预期行为,并非错误。@Concurrent修饰的函数(TaskPool任务)运行在独立的并发线程上,其参数必须满足“Sendable”规则(即可以安全跨线程传递)。应用的Context对象包含与当前UI线程/主线程强关联的资源,不允许直接跨线程传递,因此会报“Illegal context”参数错误。

2. 关于“RDB store not initialized”错误: 这个问题的核心在于RDB数据库实例(RdbStore)本身不是Sendable对象。虽然你在主线程初始化了数据库,但直接将RdbStore实例或依赖它的接口传入TaskPool是无法在子线程中访问的。

正确的实现方式(遵循你提供的指南): 文档中“使用Sendable进行大容量数据库操作”的关键是:不直接传递RdbStore,而是将数据库操作封装成“数据访问对象(DAO)模式”,并将需要操作的数据本身作为Sendable参数传递。

具体步骤修正:

  1. 在主线程:初始化获取RdbStore实例。
  2. 封装操作:将你需要进行的数据库操作(如批量插入、查询等)所必需的数据(如对象数组、查询条件等)提取出来,确保这些数据是Sendable的(如普通对象、数组、基本类型)。
  3. @Concurrent函数中:函数参数只接收这些Sendable数据。在函数内部,通过全局访问点(如获取ApplicationContext)重新获取或创建新的RDB连接,然后使用传入的数据执行操作。
  4. 使用Sendable:确保你的数据类用@Sendable装饰器标记,使其可以安全传递。

简单示例思路:

// 1. 定义Sendable数据类
@Sendable
class OperationData {
  items: Array<YourDataModel>;
}

// 2. @Concurrent函数只接收Sendable数据
@Concurrent
async function batchInsertInTaskPool(opData: OperationData): Promise<void> {
  // 3. 在函数内部,通过全局方式获取Context并初始化数据库连接
  const context = ...; // 通过合适的方式获取ApplicationContext
  const helper = new YourRdbHelper(context); // 重新初始化helper
  const rdbStore = await helper.getRdbStore(); // 获取当前线程的store实例
  // 4. 使用opData.items进行批量插入操作
  await doBatchInsert(rdbStore, opData.items);
}

// 5. 在主线程调用
let dataToProcess: OperationData = ...; // 准备数据
TaskPool.execute(batchInsertInTaskPool, dataToProcess);

总结: 你不能跨线程传递ContextRdbStore。正确做法是将数据通过Sendable方式传递到TaskPool,在TaskPool任务内部重新建立数据库连接来操作这些数据。文档中的方案正是基于此设计,请仔细检查你的实现是否将操作与数据分离。

回到顶部