GCD机制在哪里被调用?

时间:2014-08-14 08:31:33

标签: ios grand-central-dispatch

我关注RAY WENDERLICH GCD tutorial- part 2,但我不明白:

首次实施

    - (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1

        __block NSError *error;
        dispatch_group_t downloadGroup = dispatch_group_create(); // 2

        for (NSInteger i = 0; i < 3; i++) {
            NSURL *url;
            switch (i) {
                case 0:
                    url = [NSURL URLWithString:kOverlyAttachedGirlfriendURLString];
                    break;
                case 1:
                    url = [NSURL URLWithString:kSuccessKidURLString];
                    break;
                case 2:
                    url = [NSURL URLWithString:kLotsOfFacesURLString];
                    break;
                default:
                    break;
            }

            dispatch_group_enter(downloadGroup); // 3
            Photo *photo = [[Photo alloc] initwithURL:url
                                  withCompletionBlock:^(UIImage *image, NSError *_error) {
                                      if (_error) {
                                          error = _error;
                                      }
                                      dispatch_group_leave(downloadGroup); // 4
                                  }];

            [[PhotoManager sharedManager] addPhoto:photo];
        }
        dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER); // 5
        dispatch_async(dispatch_get_main_queue(), ^{ // 6
            if (completionBlock) { // 7
                completionBlock(error);
            }
        });
    });
}

第二次实施:

    - (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
    // 1
    __block NSError *error;
    dispatch_group_t downloadGroup = dispatch_group_create(); 

    for (NSInteger i = 0; i < 3; i++) {
        NSURL *url;
        switch (i) {
            case 0:
                url = [NSURL URLWithString:kOverlyAttachedGirlfriendURLString];
                break;
            case 1:
                url = [NSURL URLWithString:kSuccessKidURLString];
                break;
            case 2:
                url = [NSURL URLWithString:kLotsOfFacesURLString];
                break;
            default:
                break;
        }

        dispatch_group_enter(downloadGroup); // 2
        Photo *photo = [[Photo alloc] initwithURL:url
                              withCompletionBlock:^(UIImage *image, NSError *_error) {
                                  if (_error) {
                                      error = _error;
                                  }
                                  dispatch_group_leave(downloadGroup); // 3
                              }];

        [[PhotoManager sharedManager] addPhoto:photo];
    }

    dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{ // 4
        if (completionBlock) {
            completionBlock(error);
        }
    });
}

我是第一个实现相关代码被dispatch_async包围,一切都非常清楚。

但是,第二个实现还不清楚!我不明白,GCD机制如何处理进入和离开通知的任何部分......?

提前10倍!

2 个答案:

答案 0 :(得分:2)

第一个实现运行从

开始的后台线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1

所以整个功能在那里运行。但是这个后台线程最终在此行被阻止(它等待所有照片下载):

 dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER);

这很好,因为你没有阻止主线程。但是,这是一个笨拙的实施,

  • 你阻止一个你真正没有的线程和
  • 代码看起来有点难看,整个函数周围都有dispatch_async

所以第二个实现有两个好处:

  • 不是那个&#34;丑陋&#34;并且更具可读性(因为你摆脱了dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{}
  • 并且没有阻止,因为dispatch_group_notify充当异步完成块。

答案 1 :(得分:0)

第一种方法是异步方法。您可以从任何线程调用它,包括主线程。它将在后台线程中执行操作,一旦完成,它将在主线程上调度回调块。对此方法的调用立即返回,稍后将调用回调。

第二种方法是阻塞方法。在下载照片之前,该方法不会完成,然后它会调用您的回调方法。绝对不能从主线程调用此方法,只能从后台线程调用。