2015-04-07 3 views
0

Является ли dispatch_group и dispatch_group_notify() разумным способом ожидания параллельных задач async для завершения в Objective C с GCD?Как ждать завершения параллельных задач async в GCD?

Рассмотрим следующий пример:

dispatch_group_t requestGroup = dispatch_group_create(); 
dispatch_group_enter(requestGroup); 
dispatch_group_enter(requestGroup); 
[asyncCall1 completion:^{ 
    dispatch_group_leave(requestGroup); 
}]; 

[asyncCall2 completion:^{ 
    dispatch_group_leave(requestGroup); 
}]; 

dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{ 
    // do something now that both async calls have completed 
}); 

Это самый простой, лучший способ? Поэтому я спрашиваю, что у меня есть код, так же, как это и вообще, кажется, работает, хотя и очень редко у меня есть сбои, как:

libdispatch.dylib`dispatch_group_leave: 
0x394ea4e8: dmb ishst 
0x394ea4ec: ldrex r1, [r0, #0x28] 
0x394ea4f0: adds r1, #0x1 
0x394ea4f2: strex r2, r1, [r0, #0x28] 
0x394ea4f6: cmp r2, #0x0 
0x394ea4f8: bne 0x394ea4ec    ; dispatch_group_leave + 4 
0x394ea4fa: cmp.w r1, #0xffffffff 
0x394ea4fe: ble 0x394ea50e    ; dispatch_group_leave + 38 
0x394ea500: mvn r2, #0x80000000 
0x394ea504: cmp r1, r2 
0x394ea506: it  eq 
0x394ea508: beq.w 0x394edd54    ; _dispatch_group_wake 
0x394ea50c: bx  lr 
0x394ea50e: trap 
0x394ea510: mov r8, r8 
0x394ea512: mov r8, r8 

Является ли это несвязанный крах, который попасться группы отправки?

+1

Вы можете получить что-то подобное, если покинуть группу больше раз, чем вы ввели. Возможно ли, что это происходит в вашей ситуации? Я мог бы предложить регистрировать каждый вход и каждый выход, и убедиться, что они совпадают (или поддерживают собственный счетчик). Ясно, что, если это так просто, как здесь пример кода, это вряд ли будет проблемой, но если это сложнее, это одно дело, которое нужно учитывать. – Rob

+0

@Rob, я думаю, это невозможно, поскольку это единственные входы и выходы, которые у меня есть для этой группы. – pr1001

+0

ОК, но входящие и выходящие группы являются одним из тех чрезвычайно твердых интерфейсов, на которые многие из нас полагаются все время, поэтому я действительно не вижу, как упрощенная версия кода в вопросе могла бы создать описанный вами крах. Я подозреваю, что проблема лежит в другом месте (посторонние запросы на выезд, идентификатор группы как-то сброшен и т. Д.). Похоже, что авария находится в 'dispatch_group_leave', поэтому, если вы поднимаете один кадр в трассировке стека, он должен перейти к вашему коду, который вызвал эту функцию, и вы можете посмотреть на различные свойства/переменные там. – Rob

ответ

1

@Rob был прав, и был конкретный случай, когда блок завершения мог быть вызван дважды, что означает, что вызовы dispatch_group_leave() и dispatch_group_enter() были несбалансированными, что не поддерживается.

1

Если вы хотите подождать синхронно, вы можете использовать dispatch_group_async и dispatch_group_wait.

Подробнее (и пример): Waiting on groups of queued tasks

И, хотя я не использовал его, я уверен, что вы могли бы использовать dispatch_group_notify с dispatch_group_async, а также, что может быть немного чище, то на входе и выходе ?

+0

Это правда, когда задачи, которые вы выполняете, сами являются синхронными. Но пример OP состоит из вызовов асинхронных методов, как с их собственными обработчиками завершения. Таким образом, использование 'dispatch_group_enter' и' dispatch_group_leave' именно то, что ему нужно. Вызов 'dispatch_group_async' в этой ситуации был бы неправильным в этом сценарии. И 'dispatch_group_wait' еще хуже. Вся цель 'dispatch_group_notify' заключается в _not_ wait, а просто указать, что должно быть вызвано, когда они будут выполнены. – Rob

+1

Согласовано, если необходимо использовать 'dispatch_group_async', потребуется некоторое рефакторинг' asyncCall1' и 'asyncCall2'. – fguchelaar

Смежные вопросы