如何在Objective-C中带超时调用阻塞方法?求标准优雅实现方案
嗨,这个需求在Objective-C里有不少标准且优雅的实现方案,我给你分享两个最常用的:
方案1:GCD Dispatch Group(推荐)
这是Apple官方最推荐的并发同步方式,代码简洁且高效,完美适配你的超时等待需求:
// 创建一个dispatch组,用来跟踪异步任务 dispatch_group_t taskGroup = dispatch_group_create(); // 用全局队列来执行阻塞任务,避免阻塞主线程(如果当前是主线程的话) dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 将阻塞方法加入组并异步执行 dispatch_group_async(taskGroup, backgroundQueue, ^{ [something blockingMethod]; }); // 等待组内任务完成,最多等待2秒 long waitStatus = dispatch_group_wait(taskGroup, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC)); if (waitStatus == 0) { // 任务在2秒内顺利完成 NSLog(@"阻塞方法执行完成"); } else { // 超时,放弃等待 NSLog(@"等待超时,已停止等待"); } // ARC环境下GCD对象会自动释放,MRC环境需要手动dispatch_release(taskGroup);
这个方案的优势在于:无需手动管理线程生命周期,GCD会帮我们处理所有底层细节,代码可读性强,且性能稳定。
方案2:NSCondition 条件锁
如果你需要对线程同步有更细粒度的控制(比如中途可能需要唤醒等待),可以用NSCondition:
NSCondition *completionCondition = [[NSCondition alloc] init]; __block BOOL isTaskCompleted = NO; // 异步启动阻塞任务 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [something blockingMethod]; // 任务完成后发送信号 [completionCondition lock]; isTaskCompleted = YES; [completionCondition signal]; [completionCondition unlock]; }); // 等待信号或超时 [completionCondition lock]; if (!isTaskCompleted) { // waitUntilDate: 返回YES表示收到信号,NO表示超时 BOOL didWaitSuccessfully = [completionCondition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]]; if (didWaitSuccessfully) { NSLog(@"任务完成"); } else { NSLog(@"等待超时"); } } [completionCondition unlock];
重要提醒
如果你的blockingMethod是支持取消的任务(比如网络请求、NSOperation),一定要在超时后主动取消任务,避免资源浪费或后台无效执行。比如如果是NSURLSessionTask,超时后调用[task cancel];如果是自定义任务,要加一个取消标记让任务提前终止。
内容的提问来源于stack exchange,提问作者phnmnn
相关产品推荐
相关产品推荐

