OpenHarmony开发者论坛

标题: OpenHarmony 应用如何使用@ohos.worker多线程进行批量文件读写与复制 [打印本页]

作者: 深开鸿_苟晶晶    时间: 2024-1-19 16:17
标题: OpenHarmony 应用如何使用@ohos.worker多线程进行批量文件读写与复制
[md]# OpenHarmony 应用如何使用@ohos.worker多线程进行批量文件读写与复制

## 简介:

支持批量文件读写、复制等操作,支持使用@ohos.worker进行多线程开发。创先线程可以使用[@ohos.worker](https://gitee.com/openharmony/do ... s/js-apis-worker.md)

## 文档环境:

* 开发环境: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);
            }
          }).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 === 'deletedTag') {
              continue;
            }
            this.realFileNames.push(files);
          }
        }
        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}`);
            }
            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;
      Logger.info(TAG, ' srcPath ' + srcPath);
      destPath = message.data.destDir + '/' + fileNames;
      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 = listFiles;
        Logger.info(TAG, `Worker workerInstance::onmessage receive listFileNames: ${listFileNames}`);
      }
      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));
  };
  ```

[/md]




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5