HarmonyOS 鸿蒙Next关于TaskGroup的执行异常

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

HarmonyOS 鸿蒙Next关于TaskGroup的执行异常 需求背景:批量下载zip的需求

1:下载前先判读本地是否有zip资源包。解压缩成功则完成当前任务,如果不存在或解压缩失败,则进行第二步下载文件。

2:下载文件

3:解压缩下载后的zip文件

报错如下:

代码如下:

public parse(urls: Set<Resource>) {
  const resources = new Array<ResourceInfo>()
  urls.forEach((res) => {
    const fileInfo = this.parseUrl(res)
    if (fileInfo == undefined) return
    resources.push(fileInfo)
  })
  const needDownloadResources = new Array<ResourceInfo>()
  this.executeUnzipTask(resources).then((results) => {
    // 找出来需要下载的文件
    results.forEach((val) => {
      if (val.needDownload) {
        needDownloadResources.push(val.resource)
      }
    })
    if(needDownloadResources.length == 0) {
      console.info(`[cocos]资源解析完成`)
      return
    }
    // 执行下载任务
    this.executeDownloadTask(needDownloadResources).then((results) => {
      console.info(`[cocos]下载完成,开始解压`)
      this.executeUnzipTask(results).then((results) => {
        console.info(`[cocos]解压缩完成`)
        results.forEach((val) => {
          if (val.needDownload) {
            // 如果此处还有需要下载的文件,则忽略下载,打印错误信息
            console.error(`[cocos]已经下载过一次,忽略下载: ${val.resource.url}`)
          }
        })
      }).catch((error: Error) => {
        console.info(`[cocos]解压缩失败: ${error}`)
      })
    })
  }).catch((error: Error) => {
    console.info(`[cocos]解压缩失败: ${error}`)
  })
}

/*
 * 批量解压缩
 * */
private executeUnzipTask(resources: Array<ResourceInfo>): Promise<UnzipResponse>[] {
  console.info(`[cocos]开始解压缩${resources.length}个资源`)
  const unzipTaskGroup = new taskpool.TaskGroup()
  resources.forEach((val) => {
    unzipTaskGroup.addTask(unzipTask, val)
  })
  return taskpool.execute(unzipTaskGroup) as Promise<UnzipResponse>[]
}

/*
 * 批量下载文件
 * */
private async executeDownloadTask(resources: Array<ResourceInfo>): Promise<Array<ResourceInfo>> {
  const promises = new Array<Promise<ResourceInfo>>()
  resources.forEach(async (resource) => {
    const downloadPromise = new Promise<ResourceInfo>(async (resolve, reject) => {
      const config: request.agent.Config = {
        action: request.agent.Action.DOWNLOAD,
        url: resource.url,
        overwrite: true,
        saveas: resource.zipPath
      }
      const task = await request.agent.create(getContext(), config)
      task.on('progress', (progress) => {
        console.info(`[cocos]${resource.id} 下载进度: ${progress.processed}`)
      })
      task.on('completed', async (progress) => {
        // 执行解压缩
        resolve(resource)
      })
      task.on('failed', (progress) => {
        reject(new Error(`download failed: ${resource.url}`))
      })
      task.start()
    })
    promises.push(downloadPromise)
  })
  return Promise.all(promises).catch((error: Error) => {
    console.error(`[cocos] 下载任务失败: ${error.message}`);
    throw error;
  })
}

private parseUrl(res: Resource): ResourceInfo|undefined {
  const url = res.url
  const url_splits = url.split('/')
  if (url_splits.length == 0) return undefined
  const fileName = url_splits.pop()
  const fileNameInfoArray = fileName?.split('_md5_') ??
  if(fileNameInfoArray.length != 2) return undefined
  const md5 = fileNameInfoArray[1].replace('.zip', '')
  let unzipPath = this.unzipDir + `/${fileName?.replace('.zip', '')}`
  if (res.isPublicRes) {
    unzipPath = this.unzipDir + '/public'
  }
  const zipPath = this.zipDir + `/${fileName}`
  return {
    "url": url,
    "fileName": fileName,
    "md5": md5.toUpperCase(),
    "zipPath": zipPath,
    "unzipPath": unzipPath,
    "id": res.id
  } as ResourceInfo
}
以下是异步解压缩代码
/*
 * 对一个资源进行zip解压缩
 * 返回值:true需要下载资源,false不需要下载资源
 * */
@Concurrent
export async function unzipTask(resource: ResourceInfo): Promise<UnzipResponse> {
  const zipFileExit = await fs.access(resource.zipPath)
  if (!zipFileExit) return { resource: resource, needDownload: true }
  // zip文件存在
  const unzipFileExit = await fs.access(resource.unzipPath)
  if (!unzipFileExit) {
    await fs.mkdir(resource.unzipPath)
  }
  try {
    await zlib.decompressFile(resource.zipPath, resource.unzipPath)
    return { resource: resource, needDownload: false }
  } catch (err) {
    console.error(`解压缩失败: ${err}`)
    return { resource: resource, needDownload: true }
  }
}

更多关于HarmonyOS 鸿蒙Next关于TaskGroup的执行异常的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

麻烦提供下能复现问题的条件,具体是哪里报错,错误码是什么,最好是有能运行的demo,上面提供的代码片段缺少必要类型,且无法组成可执行工程

更多关于HarmonyOS 鸿蒙Next关于TaskGroup的执行异常的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对“HarmonyOS 鸿蒙Next关于TaskGroup的执行异常”这一问题,以下提供直接相关的解答:

在HarmonyOS中,TaskGroup是用于管理一组相关任务的机制,允许开发者更高效地调度和控制任务执行。若遇到TaskGroup执行异常,可能的原因及处理方式包括:

  1. 任务优先级冲突:检查TaskGroup中任务的优先级设置,确保没有优先级倒置或不合理设置导致的执行阻塞。

  2. 资源竞争:确认各任务间是否存在资源竞争(如共享内存、文件锁等),合理设计资源访问策略,避免死锁或饥饿现象。

  3. 任务依赖关系错误:审查TaskGroup中任务的依赖关系,确保任务执行顺序正确,无循环依赖导致无法启动。

  4. 系统资源限制:检查系统资源(如CPU、内存)使用情况,确保系统资源未被其他进程过度占用,影响TaskGroup执行。

  5. API使用不当:核对TaskGroup相关API的使用是否符合规范,包括任务创建、启动、同步等操作的正确性。

若上述检查后问题仍未解决,可能是系统级bug或特定环境下的兼容性问题。此时,建议详细记录异常现象、复现步骤及系统环境信息,提交给HarmonyOS官方进行进一步分析。

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

回到顶部