dispatch_async 嵌套是如何工作的?
How does dispatch_async nesting work?
我正在尝试理解这种常见模式:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// Background stuff on background thread
dispatch_async(dispatch_get_main_queue()) {
// Update UI on main thread
}
}
苹果文学states:
Completion callbacks can be accomplished via nested calls to the dispatch_async() function.
好的,但我认为 dispatch_async
的 FIFO 方面是它保证任务 开始 提交的顺序。我以为它不能保证它们会按任何顺序完成?
我的问题是,为什么 嵌套调用要等待其嵌套的 closure/block 完成?
如果我写
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing1()
doThing2()
doThing3()
}
那能保证doThing2()
会等到doThing1()
执行完才执行吗?如果是这样,这是否意味着它等同于两个后续的 dispatch_sync 调用,如下所示:
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing1()
}
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing2()
}
?
Ok, but I thought the FIFO aspect of dispatch_async was that it guarantees that tasks start in the order submitted. I thought it didn't guarantee that they would complete in any order?
你是对的,但这也取决于这是串行队列还是并发队列。对于串行队列,条目的顺序就是完成的顺序:在队列中的前面的项目完成之前不会发生任何新事情。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing1()
doThing2()
doThing3()
}
在那段代码中,它是什么类型的队列并不重要。您的代码都在一个块中。该块中事物的顺序不会被神奇地打乱!这会使整个编程概念变得毫无意义。
但是,其中 none 了解 Apple 在您引用的句子中的意思。嵌套完成块对于事情的工作方式至关重要,因为它们意味着您可以从主线程进入后台线程,做一些事情,然后在完成后返回主线程并做进一步的事情。这是按顺序发生的。这保证您可以遵守不得在后台线程上触摸界面的重要规则。此外,在这种安排下,来自周围区块的局部变量是可见的,因此数据可以安全地从一个区块传递到另一个区块,就像我书中的这个例子:
- (void) drawThatPuppy {
CGPoint center =
CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
dispatch_async(self->_draw_queue, ^{
CGContextRef bitmap = [self makeBitmapContext: self.bounds.size];
[self drawAtCenter: center zoom: 1 context:bitmap];
dispatch_async(dispatch_get_main_queue(), ^{
if (self->_bitmapContext)
CGContextRelease(self->_bitmapContext);
self->_bitmapContext = bitmap;
[self setNeedsDisplay];
});
});
}
我正在尝试理解这种常见模式:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// Background stuff on background thread
dispatch_async(dispatch_get_main_queue()) {
// Update UI on main thread
}
}
苹果文学states:
Completion callbacks can be accomplished via nested calls to the dispatch_async() function.
好的,但我认为 dispatch_async
的 FIFO 方面是它保证任务 开始 提交的顺序。我以为它不能保证它们会按任何顺序完成?
我的问题是,为什么 嵌套调用要等待其嵌套的 closure/block 完成?
如果我写
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing1()
doThing2()
doThing3()
}
那能保证doThing2()
会等到doThing1()
执行完才执行吗?如果是这样,这是否意味着它等同于两个后续的 dispatch_sync 调用,如下所示:
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing1()
}
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing2()
}
?
Ok, but I thought the FIFO aspect of dispatch_async was that it guarantees that tasks start in the order submitted. I thought it didn't guarantee that they would complete in any order?
你是对的,但这也取决于这是串行队列还是并发队列。对于串行队列,条目的顺序就是完成的顺序:在队列中的前面的项目完成之前不会发生任何新事情。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
doThing1()
doThing2()
doThing3()
}
在那段代码中,它是什么类型的队列并不重要。您的代码都在一个块中。该块中事物的顺序不会被神奇地打乱!这会使整个编程概念变得毫无意义。
但是,其中 none 了解 Apple 在您引用的句子中的意思。嵌套完成块对于事情的工作方式至关重要,因为它们意味着您可以从主线程进入后台线程,做一些事情,然后在完成后返回主线程并做进一步的事情。这是按顺序发生的。这保证您可以遵守不得在后台线程上触摸界面的重要规则。此外,在这种安排下,来自周围区块的局部变量是可见的,因此数据可以安全地从一个区块传递到另一个区块,就像我书中的这个例子:
- (void) drawThatPuppy {
CGPoint center =
CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
dispatch_async(self->_draw_queue, ^{
CGContextRef bitmap = [self makeBitmapContext: self.bounds.size];
[self drawAtCenter: center zoom: 1 context:bitmap];
dispatch_async(dispatch_get_main_queue(), ^{
if (self->_bitmapContext)
CGContextRelease(self->_bitmapContext);
self->_bitmapContext = bitmap;
[self setNeedsDisplay];
});
});
}