dispatch_async嵌套如何工作?

时间:2015-07-19 16:08:23

标签: cocoa grand-central-dispatch dispatch-async

我试图理解这种常见模式:

    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
        }
    }

Apple文献states

  

完成回调可以通过对dispatch_async()函数的嵌套调用来完成。

好的,但我认为dispatch_async的FIFO方面是它保证在提交的顺序中开始的任务。我认为它并不能保证它们能以任何顺序完成吗?

我的问题是,为什么嵌套调用是否等待它嵌套的闭包/阻塞的完成?

如果我要写

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()
}

1 个答案:

答案 0 :(得分:0)

  

好的,但我认为dispatch_async的FIFO方面是它保证任务以提交的顺序开始。我认为它并不能保证它们能以任何顺序完成吗?

您是对的,但这也取决于这是一个串行还是并发队列。对于串行队列,输入顺序是完成顺序:在队列中的前面的项目完成之前不会发生任何新的事情。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        doThing1()
        doThing2()
        doThing3()
}

在该代码中,它与哪种队列无关。你的代码都在一个区块内。该块中的事物顺序不会被神奇地洗牌!这将使整个编程概念无意义。

然而,在你引用的句子中,没有一个能达到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];
        });
    });
}