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

UIViewController如何等待其他类中执行的dispatch_async任务完成?

问题根源

当前现象是GCD异步API的正常表现:dispatch_async会将任务提交到队列后立刻返回,不会等待任务执行完成,因此你写在调用语句后的代码会立刻执行,不会等待异步任务结束。

可行解决方案

方案1:将后续逻辑移入回调Block(最推荐)

这是最符合异步编程规范的方案,不会阻塞任何线程,也不会出现死锁风险,直接把需要等待异步结束后执行的代码放到completionHandler回调中即可:

[dispatch_thread addNumber:5 withNumber:7 andCompletionHandler:^(int result) {
    NSLog(@"The dispatch from class finished ...%i",result);
    // 后续逻辑移到此处
    NSLog(@"Continue after dispatch_async finished ...");
}];

方案2:使用dispatch_group异步监听任务完成

如果后续逻辑不能和回调内容耦合,可以用调度组监听任务完成状态,不会阻塞当前线程:

dispatch_group_t taskGroup = dispatch_group_create();
// 标记任务开始
dispatch_group_enter(taskGroup);
[dispatch_thread addNumber:5 withNumber:7 andCompletionHandler:^(int result) {
    NSLog(@"The dispatch from class finished ...%i",result);
    // 标记任务结束
    dispatch_group_leave(taskGroup);
}];
// 监听所有任务完成,指定后续逻辑执行的队列
dispatch_group_notify(taskGroup, dispatch_get_main_queue(), ^{
    NSLog(@"Continue after dispatch_async finished ...");
});

方案3:使用dispatch_semaphore实现同步等待

如果确实需要阻塞当前线程等待任务完成,可以用信号量实现,注意:禁止在主线程调用该方案,否则会出现死锁:你的completionHandler是回调到主线程执行的,主线程卡在等待步骤时,回调永远无法执行,导致程序卡住:

// 初始化信号量,初始值为0
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[dispatch_thread addNumber:5 withNumber:7 andCompletionHandler:^(int result) {
    NSLog(@"The dispatch from class finished ...%i",result);
    // 发送信号,信号量+1
    dispatch_semaphore_signal(sem);
}];
// 等待信号量,信号量大于0时才会继续往下执行
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
NSLog(@"Continue after dispatch_async finished ...");

方案4:自定义类新增同步执行接口

如果该工具类经常有同步等待的需求,可以新增同步调用的方法:

  1. 头文件新增声明:
@interface dispatch_thread : NSObject
// 原有方法保留
+(void)addNumber:(int)number1 withNumber:(int)number2 andCompletionHandler:(void (^)(int result))completionHandler;
// 新增同步方法声明
+(void)syncAddNumber:(int)number1 withNumber:(int)number2 andCompletionHandler:(void (^)(int result))completionHandler;
@end
  1. 实现文件新增实现:
@implementation dispatch_thread
// 原有方法实现保留
+(void)addNumber:(int)number1 withNumber:(int)number2 andCompletionHandler:(void (^)(int result))completionHandler{
    // 原有实现不变
}

// 新增同步方法实现
+(void)syncAddNumber:(int)number1 withNumber:(int)number2 andCompletionHandler:(void (^)(int result))completionHandler{
    int result = number1 + number2;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // 改用dispatch_sync同步提交任务,会等待任务执行完成再返回
    dispatch_sync(queue, ^{
        int i=1000;
        while (i>0) {
            NSLog(@"doing something in class...%i",i);
            i--;
        }
        // 线程安全处理,避免死锁
        if ([NSThread isMainThread]) {
            NSLog(@"callback in class...");
            completionHandler(result);
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"callback in class...");
                completionHandler(result);
            });
        }
    });
}
@end

调用时直接使用同步方法即可,调用后的代码会自动等待任务完成后执行:

[dispatch_thread syncAddNumber:5 withNumber:7 andCompletionHandler:^(int result) {
    NSLog(@"The dispatch from class finished ...%i",result);
}];
NSLog(@"Continue after dispatch_async finished ...");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:54:07