积分104 / 贡献0

提问1答案被采纳1文章7

作者动态

[经验分享] OpenHarmony 应用如何使用@ohos.worker多线程进行批量文件读写与复制 原创

深开鸿_苟晶晶 显示全部楼层 发表于 2024-1-19 16:17:13

OpenHarmony 应用如何使用@ohos.worker多线程进行批量文件读写与复制

简介:

支持批量文件读写、复制等操作,支持使用@ohos.worker进行多线程开发。创先线程可以使用@ohos.worker

文档环境:

  • 开发环境:Windows 11 家庭版
  • DevEco Studio版本:DevEco Studio 4.0 Release(4.0.0.600)
  • SDK版本:4.0.10.13
  • 开发板型号:DAYU200(RK3568)
  • 系统版本:OpenHarmony 4.1.5.2

演示 demo:

  • 新建一个 Stage 框架的 demo 工程,在entryability/EntryAbility.ets中通过 let filesDir = this.context.filesDir;AppStorage.SetOrCreate('sanBoxFileDir', filesDir);存储沙箱files路径信息,然后在pages/CopyFile.ets中通过public baseDir: string | undefined = AppStorage.Get('sanBoxFileDir');拿到应用的沙箱files路径信息,通过文件操作接口在files下创建文件夹workerDir并创建以txt为后缀的文件。

  • 通过接口fs.listFileSync(filesPathDir)获取workerDir文件夹下的所有文件并显示在list中。

  • 用户点击多选框选择需要批量拷贝的文件,通过new worker.ThreadWorker('entry/ets/workers/WorkerCopy.ets')创建worker线程并将拷贝文件的信息发送至worker线程,在该线程中通过fs.copyFileSync(srcPath, destPath)实现文件拷贝操作,文件拷贝成功之后向主线程发送拷贝成功消息:workerPort.postMessage({count: count,strFlag: true,listFileNames: listFileNames}); 核心代码如下: 在沙箱路径下创建待拷贝的文件:

    readyFilesToWorker(): void {
        let content = CONTENT + CONTENT + new Date() + '\n';
        let workerDir = this.baseDir + '/workerDir';
    
        try {
          if (!fs.accessSync(workerDir)) {
            fs.mkdirSync(workerDir);
          }
          Logger.info(TAG, 'readyFilesToWorker dpath = ' + workerDir);
          for (let i = 0; i < FILE_NUM; i++) {
            let myFile = '';
            if (i < FILE_NUMBER) {
              myFile = workerDir + `/TestFile0${i + 1}.txt`;
            } else {
              myFile = workerDir + `/TestFile${i + 1}.txt`;
            }
            Logger.info(TAG, 'readyFilesToWorker myFile = ' + myFile);
            let file = fs.openSync(myFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
            fs.writeSync(file.fd, content);
            fs.closeSync(file);
          }
          Logger.info(TAG, 'readyFilesToWorker successful');
        } catch (e) {
          Logger.error(TAG, `readyFilesToWorker has failed for: {message: ${(e as BusinessError).message}, code: ${(e as BusinessError).code}}`);
        }
      }

    创建worker线程并发送拷贝的文件信息:

    async workToCopyFiles(files: Array<string>, filePath: string): Promise<void> {
        try {
          Logger.info(TAG, 'WorkCreator start to create worker');
          let destPath = filePath;
          Logger.info(TAG, 'Workerets destPath ' + destPath);
          if (!fs.accessSync(destPath)) {
            fs.mkdirSync(destPath);
          }
          if (fs.accessSync(destPath)) {
            fs.listFile(destPath).then((filenames) => {
              Logger.info(TAG, 'listFile succeed');
              for (let i = 0; i < filenames.length; i++) {
                Logger.info(TAG, 'Workerets fileName: ' + filenames[i]);
              }
            }).catch((err: BusinessError) => {
              Logger.info(TAG, 'list file failed with error message: ' + err.message + ', error code: ' + err.code);
            });
          }
          if (files !== null) {
            this.realFileNames.length = 0;
            for (let i = 0; i < files.length; i++) {
              if (files[i] === 'deletedTag') {
                continue;
              }
              this.realFileNames.push(files[i]);
            }
          }
          let count = this.realFileNames.length;
          for (let j = 0; j < count; j++) {
            Logger.info(TAG, 'workToCopyFiles this.realFileNames = ' + this.realFileNames[j]);
          }
          workerInstance = new worker.ThreadWorker('entry/ets/workers/WorkerCopy.ts');
          if (this.realFileNames !== null) {
            let srcPath = this.baseDir + '/workerDir';
            workerInstance.postMessage({
              srcDir: srcPath,
              destDir: destPath,
              fileNames: this.realFileNames
            });
          }
    
          workerInstance.onexit = (code): void => {
            Logger.info(TAG, `workerInstance::onexit has been exit ${code}`);
          };
          workerInstance.onerror = (err): void => {
            Logger.info(TAG, `workerInstance::onerror has errors: ${JSON.stringify(err)}`);
          };
          workerInstance.onmessageerror = (event): void => {
            Logger.info(TAG, `workerInstance::onmessageerror has errors: ${JSON.stringify(event)}`);
          };
          workerInstance.onmessage = (message): void => {
            Logger.info(TAG, `workerInstance::onmessage receive data: ${JSON.stringify(message.data)}`);
            if (message.data.hasOwnProperty('count')) {
              Logger.info(TAG, `workerInstance::onmessage receive data length = ${message.data.count}`);
              this.filesCount = message.data.count;
              fileFlag = message.data.strFlag;
              this.flag = true;
              let fileName1: string | null = null;
              let fileName2: string | null = null;
              for (let i: number = 0; i < message.data.listFileNames.length; i++) {
                Logger.info(TAG, `Worker workerInstance::onmessage receive listFileNames: ${message.data.listFileNames[i]}`);
              }
              if (message.data.listFileNames[0] !== undefined && message.data.listFileNames[1] !== undefined && message.data.listFileNames[LIST_FILE_TWO] === undefined) {
                fileName1 = message.data.listFileNames[0] + '、';
                fileName2 = message.data.listFileNames[1];
              } else if (message.data.listFileNames[0] !== undefined && message.data.listFileNames[1] === undefined) {
                fileName1 = message.data.listFileNames[0];
                fileName2 = '';
              } else {
                fileName1 = message.data.listFileNames[0] + '、';
                let copyFileLog: string | undefined = AppStorage.Get('copyFileLog5');
                fileName2 = message.data.listFileNames[1] + copyFileLog;
              }
              AppStorage.SetOrCreate('fileListName1', fileName1);
              AppStorage.SetOrCreate('fileListName2', fileName2);
              let copyFileLog3: string | undefined = AppStorage.Get('copyFileLog3');
              let copyFileLog4: string | undefined = AppStorage.Get('copyFileLog4');
              let copyFileLog = '2、' + fileName1 + fileName2 + copyFileLog3 + 'copy' + copyFileLog4;
              if (fileName1 !== 'undefined、') {
                AppStorage.SetOrCreate('copyFileShowLog', copyFileLog);
              } else {
                AppStorage.SetOrCreate('copyFileShowLog', $r('app.string.workerLogChooseFile'));
              }
              Logger.info(TAG, `Worker workerInstance::onmessage receive count: ${JSON.stringify(this.filesCount)}`);
            }
            if (this.filesCount !== 0) {
              AppStorage.SetOrCreate('fileNumber', JSON.stringify(this.filesCount));
            } else {
              AppStorage.SetOrCreate('fileNumber', '0');
              AppStorage.SetOrCreate('fileListName1', '');
              AppStorage.SetOrCreate('fileListName2', '');
            }
            Logger.info(TAG, 'workerInstance::onmessage Finish to process data from WorkerCopy.ts');
            workerInstance?.terminate();
          };
          while (!fileFlag) {
            await sleep(SLEEP_TIME);
          }
        } catch (e) {
          Logger.error(TAG, `Worker WorkCreator error package: message: ${(e as BusinessError).message}, code: ${(e as BusinessError).code}`);
        }
      }

    worker线程实现拷贝:

    import worker from '@ohos.worker';
    import type { ThreadWorkerGlobalScope } from '@ohos.worker';
    import Logger from '../common/Logger';
    import fs from '@ohos.file.fs';
    
    const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
    const TAG: string = '[ConcurrentModule].[WorkerCopy]';
    
    workerPort.onmessage = (message): void => {
      let srcPath: string = null;
      let destPath: string = null;
      let fileNames: string = message.data.fileNames;
      for (let i = 0; i < fileNames.length; i++) {
        srcPath = message.data.srcDir + '/' + fileNames[i];
        Logger.info(TAG, ' srcPath ' + srcPath);
        destPath = message.data.destDir + '/' + fileNames[i];
        Logger.info(TAG, ' destPath ' + destPath);
        try {
          fs.copyFileSync(srcPath, destPath);
          let countTest = fs.listFileSync(message.data.destDir).length;
          Logger.info(TAG, `Worker workerInstance::onmessage receive countTest: ${countTest}`);
        } catch (e) {
          Logger.error(TAG, 'WorkerCopy::copyFile has failed for: ' + JSON.stringify(e));
        }
      }
      let listFileNames = [];
      listFileNames.length = 0;
      try {
        let count = fs.listFileSync(message.data.destDir).length;
        let listFiles = fs.listFileSync(message.data.destDir);
        Logger.info(TAG, 'listFile succeed');
        for (let i = 0; i < listFiles.length; i++) {
          listFileNames[i] = listFiles[i];
          Logger.info(TAG, `Worker workerInstance::onmessage receive listFileNames: ${listFileNames[i]}`);
        }
        workerPort.postMessage({
          count: count,
          strFlag: true,
          listFileNames: listFileNames
        });
        Logger.info(TAG, 'WorkerCopy::onmessage thread post message successfully');
      } catch (e) {
        Logger.error(TAG, 'WorkerCopy::onmessage has failed for: ' + JSON.stringify(e));
      }
    };
    
    workerPort.onmessageerror = async (message): Promise<void> => {
      Logger.error(TAG, 'WorkerCopy::onmessageerror : ' + JSON.stringify(message));
    };
    
    workerPort.onerror = (e): void => {
      Logger.error(TAG, 'WorkerCopy::onerror : ' + JSON.stringify(e));
    };

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部