iOS开发之GCD -- dispatch_group

组   dispatch_group

很多时候,你发现需要将异步的 block 组合起来去完成一个给定的任务。这些任务中甚至有些是并行的。现在,如果你想要在这些任务都执行完成后运行一些代码,"groups" 可以完成这项任务。看这里的例子:

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^(){
    // Do something that takes a while
    [self doSomeFoo];
    dispatch_group_async(group, dispatch_get_main_queue(), ^(){
        self.foo = 42;
    });
});
dispatch_group_async(group, queue, ^(){
    // Do something else that takes a while
    [self doSomeBar];
    dispatch_group_async(group, dispatch_get_main_queue(), ^(){
        self.bar = 1;
    });
});

// This block will run once everything above is done:
dispatch_group_notify(group, dispatch_get_main_queue(), ^(){
    NSLog(@"foo: %d", self.foo);
    NSLog(@"bar: %d", self.bar);
});

需要注意的重要事情是,所有的这些都是非阻塞的。我们从未让当前的线程一直等待直到别的任务做完。恰恰相反,我们只是简单的将多个 block 放入队列。由于代码不会阻塞,所以就不会产生死锁。

同时需要注意的是,在这个小并且简单的例子中,我们是怎么在不同的队列间进切换的。

对现有API使用 dispatchgroupt

一旦你将 groups 作为你的工具箱中的一部分,你可能会怀疑为什么大多数的异步API不把 dispatch_group_t 作为一个可选参数。这没有什么无法接受的理由,仅仅是因为自己添加这个功能太简单了,但是你还是要小心以确保自己使用 groups 的代码是成对出现的。

举例来说,我们可以给 Core Data 的 -performBlock: API 函数添加上 groups,就像这样:

- (void)withGroup:(dispatch_group_t)group performBlock:(dispatch_block_t)block
{
    if (group == NULL) {
        [self performBlock:block];
    } else {
        dispatch_group_enter(group);
        [self performBlock:^(){
            block();
            dispatch_group_leave(group);
        }];
    }
}

当 Core Data 上的一系列操作(很可能和其他的代码组合起来)完成以后,我们可以使用 dispatch_group_notify 来运行一个 block 。

很明显,我们可以给 NSURLConnection 做同样的事情:

+ (void)withGroup:(dispatch_group_t)group 
        sendAsynchronousRequest:(NSURLRequest *)request 
        queue:(NSOperationQueue *)queue 
        completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
{
    if (group == NULL) {
        [self sendAsynchronousRequest:request 
                                queue:queue 
                    completionHandler:handler];
    } else {
        dispatch_group_enter(group);
        [self sendAsynchronousRequest:request 
                                queue:queue 
                    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
            handler(response, data, error);
            dispatch_group_leave(group);
        }];
    }
}

为了能正常工作,你需要确保:

  • dispatch_group_enter() 必须要在 dispatch_group_leave()之前运行。
  • dispatch_group_enter() 和 dispatch_group_leave() 一直是成对出现的(就算有错误产生时)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值