今天我尝试了以下代码:
- (void)suspendTest {
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_BACKGROUND, 0);
dispatch_queue_t suspendableQueue = dispatch_queue_create("test", attr);
for (int i = 0; i <= 10000; i++) {
dispatch_async(suspendableQueue, ^{
NSLog(@"%d", i);
});
if (i == 5000) {
dispatch_suspend(suspendableQueue);
}
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"Show must go on!");
dispatch_resume(suspendableQueue);
});
}
代码启动了 10001 个任务,但它应该暂停队列中途运行新任务,以便在 6 秒后恢复。此代码按预期工作 - 执行了 5000 个任务,然后队列停止,6 秒后它恢复。
但是如果我使用串行队列而不是并发队列,我的行为就不清楚了。
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_BACKGROUND, 0);
在这种情况下,随机数量的任务在挂起之前设法执行,但通常这个数字接近于零(挂起发生在任何任务之前)。
问题是 - 为什么挂起对于串行队列和并发队列的工作方式不同以及如何正确挂起串行队列?
Best Answer-推荐答案 strong>
按照其名称,串行队列按顺序执行任务,即仅在前一个任务完成后从下一个任务开始。优先级是后台,所以当当前队列到达第 5000 个任务并挂起队列时,它甚至可能还没有开始第一个任务。
来自dispatch_suspend 的文档:
The suspension occurs after completion of any blocks running at the time of the call.
也就是说,它没有保证队列中异步分派(dispatch)的任务会完成,只是任何当前正在运行的任务( block )都不会在中途暂停。在串行队列上最多可以有一个任务“当前正在运行”,而在并发队列上则没有指定的上限。 编辑: 根据您对一百万个任务的测试,并发队列似乎维护了它“完全并发”的概念抽象,因此即使它们实际上都认为它们“当前正在运行”不是。
要在第 5000 个任务之后暂停它,您可以从第 5000 个任务本身触发它。 (那么您可能还想从暂停时间开始启动恢复计时器,否则理论上如果恢复发生在暂停之前,它可能永远不会恢复。)
关于ios - 挂起串行队列,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/40184693/
|