2014-02-15 3 views
2

я направляю ряд действий, подобный этому:Ответный когда несколько dispatch_async() закончили

for (int x = 0; x < 1000; x++) 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul), 
    ^{ 
     //Do stuff 
    }); 

Как только все они закончили выполнение Я хочу вызвать другой метод [self someMethod]; или послать другой последний блок , не имеет значения, какой.

Как я могу это достичь?

ответ

1

Вы можете использовать группы отправки или барьер доставки. Оба документа хорошо документированы.

Однако такой параллелизм - массовая отправка в асинхронную очередь - в значительной степени гарантируется медленность, ресурс голоден и, скорее всего, приведет к тому, что ваше приложение будет отброшено для использования в памяти.

Асинхронная отправка должен порождать поток, если поток еще не доступен для начала обработки. По определению, асинхронные отправления в глобальную параллельную очередь не могут быть дросселированы каким-либо образом, так как это приведет к очень случайным взаимоблокировкам очень быстро, когда блок А имеет зависимость от блока B, но блок B не может быть выполнен до тех пор, пока не закончится блок A (например,).

Параллелизм должен всегда быть дросселированным.

+0

Это неясно мне, как предсказать наихудшее количество потоков, которые могли бы создать НОД. Легко ли заканчивать одним потоком для каждой отправки, даже если они не зависят друг от друга каким-либо образом? –

+1

Ключ заключается в том, работают ли какие-либо блоки на любом (блокировка, диск или сеть io и т. Д.). Для чисто вычислительной работы процессора GCD хорошо справится. После блокировки вызовов он не имеет достаточной информации для надлежащего дросселирования. –

+0

@Catfish_Man Даже для чисто вычислительной работы, если вы отправляете 100 длинных блоков в асинхронную очередь, вы, скорее всего, получите 100 потоков. GCD не может дросселировать отправку блоков на асинхронные очереди, потому что GCD не знает, какие зависимости могут существовать между ними. Даже API-интерфейс зависимостей в NSOperationQueue можно считать консультативным; он не может знать, что операция A блоков B и, следовательно, B затухает от выполнения, потому что A работает, является недопустимым состоянием. – bbum

1

Метод, который я использовал в прошлом, - это сделать NSOperationQueue с ограниченным количеством параллелизма (скажем, 3 параллельных операции), а затем отправить каждый блок как NSBlockOperation. Наконец, я создаю завершение NSBlockOperation, которое зависит от завершения всех других операций. Я завершаю все операции, включая операцию завершения. Конструкция зависимостей NSOperations заставляет независимые компоненты завершить работу до завершения окончательной операции завершения.

Этот подход обеспечивает возможность выполнять работу после того, как куча других блоков будет завершена, и это уменьшит общее влияние запуска пучка потоков одновременно и ждет их завершения.

См addDependency: метод класса NSOperation (https://developer.apple.com/library/mac/documentation/cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/cl/NSOperation)

+1

Это работает; одно предостережение. Если у вас есть группа данных, стоящих в очереди для обработки, не вставляйте в очередь все блоки одновременно. Это будет пустой тратой памяти.Вместо этого достаточно заполнить достаточное количество блоков, чтобы полностью использовать ваш расчетный конвейер. Это делает общее использование ресурсов более эффективным, делая отмену менее ресурсоемкой. – bbum

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