Я просматриваю учебник Рэя Вендерлиха по использованию очередей отправки, чтобы получать уведомления о завершении группы задач. http://www.raywenderlich.com/63338/grand-central-dispatch-in-depth-part-2
Первый код, показанный в разделе «Код, который работает», взят прямо из учебника. Представление «Предупреждение» (финальный блок завершения) выполняется после завершения всех 3 загрузок.
Я попытался поиграть с этим и переместил асинхронную отправку вниз в «Код, который не работает», чтобы посмотреть, что произойдет, если dispatch_group_create() и dispatch_group_enter() произойдут в разных очередях. В этом случае, dispatch_group_enter(), похоже, не регистрируется, потому что dispatch_group_wait() немедленно завершается, а представление предупреждения (окончательный блок завершения) выполняется еще до завершения всех загрузок.
Кто-нибудь может объяснить, что происходит во втором случае? (Это просто для моего понимания того, как работает диспетчерская группа, и я понимаю, что лучше поместить всю функцию в глобальную параллельную очередь, чтобы избежать блокировки основного потока).
Код, который работает
- (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^{
__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);
__block Photo *photo = [[Photo alloc] initwithURL:url
withCompletionBlock:^(UIImage *image, NSError *_error) {
if (_error) {
error = _error;
}
NSLog(@"Finished completion block for photo alloc for URL %@ and photo is %@",url,photo) ;
dispatch_group_leave(downloadGroup);
}];
[[PhotoManager sharedManager] addPhoto:photo];
NSLog(@"Finished adding photo to shared manager for URL %@ and photo is %@",url,photo) ;
}
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER); // 5
dispatch_async(dispatch_get_main_queue(), ^{
if (completionBlock) {
NSLog(@"Executing completion block after download group complete") ;
completionBlock(error);
}
}) ;
}) ;
}
ОТРЕДАКТИРОВАНО Код, который не работает с дополнительными операторами NSLog
Код, который не работает
- (void)downloadPhotosWithCompletionBlock:(BatchPhotoDownloadingCompletionBlock)completionBlock
{
__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_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^{
dispatch_group_enter(downloadGroup);
NSLog(@"Enetered group for URL %@",url) ;
__block Photo *photo = [[Photo alloc] initwithURL:url
withCompletionBlock:^(UIImage *image, NSError *_error) {
if (_error) {
error = _error;
}
NSLog(@"Finished completion block for photo alloc for URL %@ and photo is %@",url,photo) ;
dispatch_group_leave(downloadGroup);
}];
[[PhotoManager sharedManager] addPhoto:photo];
NSLog(@"Finished adding photo to shared manager for URL %@ and photo is %@",url,photo) ;
}) ;
}
NSLog(@"Executing wait statement") ;
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER); // 5
dispatch_async(dispatch_get_main_queue(), ^{
if (completionBlock) {
NSLog(@"Executing completion block after download group complete") ;
completionBlock(error);
}
}) ;
}