如何将NSOperation调度到队列头部并让其余所有操作等待其执行完成
实现方案
不需要逐个修改现有操作的依赖关系,推荐两种高效实现思路:
方案1:队列挂起 + 独立重试执行(改造成本最低)
- 监听到特定操作失败时,第一时间调用原队列的
setSuspended:YES,此时队列会暂停调度所有未出队的待执行操作,已经在运行的操作会正常执行完毕,不会被中断 - 初始化重试操作,设置
qualityOfService为NSQualityOfServiceUserInteractive保证最高调度优先级,添加完成回调:- 重试成功时调用原队列的
setSuspended:NO恢复队列调度 - 重试如果继续失败,按你的重试策略再次执行该操作即可
- 重试成功时调用原队列的
- 将重试操作提交到系统全局高优先级队列单独执行,不需要加入原有队列,完全避开依赖修改
代码示例:
// 原有业务队列定义 NSOperationQueue *businessQueue = [[NSOperationQueue alloc] init]; businessQueue.maxConcurrentOperationCount = 4; // 特定操作失败回调 - (void)specificOperationDidFail:(NSOperation *)failedOp { // 暂停原有业务队列 businessQueue.suspended = YES; // 创建重试操作 NSBlockOperation *retryOp = [NSBlockOperation blockOperationWithBlock:^{ // 执行你的重试逻辑 [self retrySpecificOperation]; }]; // 设置最高优先级 retryOp.qualityOfService = NSQualityOfServiceUserInteractive; retryOp.queuePriority = NSOperationQueuePriorityVeryHigh; // 重试完成回调 [retryOp setCompletionBlock:^{ if (retryOp.isCancelled || /* 自定义重试失败判断逻辑 */) { // 按需处理多次重试逻辑 [self specificOperationDidFail:retryOp]; return; } // 重试成功恢复原有队列 dispatch_async(dispatch_get_main_queue(), ^{ businessQueue.suspended = NO; }); }]; // 提交到独立队列执行,不占用原有业务队列资源 [[[NSOperationQueue alloc] init] addOperation:retryOp]; }
方案2:全局条件锁控制(支持中断正在执行的普通操作)
如果需要连已经启动的普通操作也暂停等待,可在所有普通操作的main方法开头加入全局条件判断:
- 定义全局条件锁
NSCondition *retryCondition = [[NSCondition alloc] init];和全局标志BOOL isWaitingForCriticalRetry = NO; - 特定操作失败时,先置
isWaitingForCriticalRetry = YES,再启动重试操作 - 所有普通操作的
main方法执行逻辑前,先判断等待标志:
- (void)main { if (self.isCancelled) return; [retryCondition lock]; while (isWaitingForCriticalRetry) { [retryCondition wait]; if (self.isCancelled) { [retryCondition unlock]; return; } } [retryCondition unlock]; // 原有操作业务逻辑 }
- 重试成功后修改标志并唤醒所有等待的操作:
[retryCondition lock]; isWaitingForCriticalRetry = NO; [retryCondition broadcast]; [retryCondition unlock];
内容的提问来源于stack exchange,提问作者Patroclus
相关产品推荐
相关产品推荐

