You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多异步线程下更新MBProgressHUD进度条及QoS警告问题求助

解决MBProgressHUD进度更新及QoS优先级反转警告问题

一、先搞定进度不更新的核心问题

你这进度不更新,大概率是直接用单个任务的进度更新HUD,多个任务进度互相覆盖,再加上HUD没配置成进度模式导致的。按下面步骤调整:

  1. 把HUD改成进度显示模式
    初始化HUD时必须指定进度模式,默认模式是加载转圈,不会显示进度条:

    self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    self.hud.mode = MBProgressHUDModeDeterminate; // 条形进度条,想用环形就换MBProgressHUDModeAnnularDeterminate
    self.hud.label.text = @"上传中...";
    self.hud.detailsLabel.text = @"0%";
    

    注意给HUD加个控制器的强引用属性,别用局部变量导致提前释放。

  2. 计算总上传进度,别单独用单个任务进度
    4个任务各占总进度的25%,得把每个任务的进度按权重累加。在控制器里加两个变量:

    @property (nonatomic, assign) CGFloat totalUploadProgress;
    @property (nonatomic, assign) NSInteger finishedTaskCount;
    

    然后在每个上传任务的progress回调里更新总进度:

    __weak typeof(self) weakSelf = self;
    [uploadManager uploadImage:image progress:^(CGFloat percent) {
        // 单个任务进度占总进度的25%,计算当前任务的贡献值
        CGFloat currentTaskContribution = percent * 0.25;
        // 减去之前该任务的贡献值,避免重复累加
        CGFloat previousTaskProgress = weakSelf.totalUploadProgress - (weakSelf.finishedTaskCount * 0.25);
        weakSelf.totalUploadProgress = weakSelf.totalUploadProgress - previousTaskProgress + currentTaskContribution;
        
        // 切主队列更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            weakSelf.hud.progress = weakSelf.totalUploadProgress;
            weakSelf.hud.detailsLabel.text = [NSString stringWithFormat:@"%.0f%%", weakSelf.totalUploadProgress * 100];
        });
    } completion:^(BOOL success) {
        weakSelf.finishedTaskCount++;
        if (weakSelf.finishedTaskCount == 4) {
            [MBProgressHUD hideHUDForView:weakSelf.view animated:YES];
            // 上传完成后的逻辑
        }
    }];
    

二、解决QoS优先级反转警告

那个紫色警告是因为上传回调的线程没指定QoS等级,而你发起上传的队列是QOS_CLASS_USER_INITIATED级别,导致优先级反转。按下面两种方式处理:

  1. 给上传回调队列指定对应QoS
    如果你的上传方法支持传入回调队列,直接指定和发起队列相同的QoS:

    // 创建带USER_INITIATED优先级的回调队列
    dispatch_queue_t uploadCallbackQueue = dispatch_queue_create("com.yourapp.upload.callback", DISPATCH_QUEUE_CONCURRENT);
    dispatch_set_target_queue(uploadCallbackQueue, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0));
    
    // 传入自定义队列作为回调队列
    [uploadManager uploadImage:image callbackQueue:uploadCallbackQueue progress:^(CGFloat percent) {
        // 这里回调线程已经是USER_INITIATED级别,再切主队列就不会触发警告
        dispatch_async(dispatch_get_main_queue(), ^{
            // 更新HUD逻辑
        });
    } completion:nil];
    
  2. 别用dispatch_group_wait阻塞高优先级队列
    如果你之前用了dispatch_group_wait在主线程或USER_INITIATED队列里,这会直接导致警告——因为wait会阻塞高优先级队列,等待低优先级的上传任务完成。改成用dispatch_group_notify处理完成事件:

    dispatch_group_t uploadGroup = dispatch_group_create();
    
    // 每个上传任务加入group
    dispatch_group_enter(uploadGroup);
    [uploadManager uploadImage:image progress:^(CGFloat percent) {
        // 更新进度
    } completion:^(BOOL success) {
        dispatch_group_leave(uploadGroup);
    }];
    
    // 用notify监听完成,而非wait阻塞
    dispatch_group_notify(uploadGroup, dispatch_get_main_queue(), ^{
        [MBProgressHUD hideHUDForView:self.view animated:YES];
        // 上传完成逻辑
    });
    

三、额外检查点

  • 先加NSLog确认上传任务的progress回调是否真的触发,percent值有没有变化;
  • 别在progress回调里做耗时操作,只保留UI更新的最小逻辑;
  • 确保所有上传任务的completion回调都正确调用了dispatch_group_leave,避免group一直等待。

内容的提问来源于stack exchange,提问作者Christopher Sonny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:49:51