Использование единого общего фонового потока для обработки данных iOS? - PullRequest
5 голосов
/ 14 ноября 2011

У меня есть приложение, в котором я загружаю несколько ресурсов из сети и выполняю некоторую обработку каждого из них.Я не хочу, чтобы эта работа происходила в основном потоке, но она довольно легкая и с низким приоритетом, поэтому все это может действительно происходить в одном и том же общем рабочем потоке.Кажется, что это было бы хорошо, потому что работа, необходимая для настройки и разрушения всех этих рабочих потоков (ни одна из которых не будет длиться долго, и т.хотя, кажется, не существует простого способа заставить всю эту работу происходить в одном общем потоке , а не создавать новый поток для каждой задачи.Это осложняется большим количеством путей к достижению параллелизма, которые, кажется, возникли за эти годы.(Явный NSThreads, NSOperationQueue, GCD и т. Д.)

Я переоцениваю издержки, связанные с порождением всех этих потоков?Должен ли я просто не потеть и использовать более легкие подходы для каждой задачи?Использовать GCD, и предположить, что он умнее, чем я, по поводу использования (повторного) потока?

Ответы [ 3 ]

8 голосов
/ 14 ноября 2011

Использование GCD - это текущая официальная рекомендация и требует меньше усилий, чем любое другое решение. Если вам явно необходимо, чтобы вещи, которые вы передаете, происходили последовательно (то есть, как если бы они находились в одном потоке), тогда вы можете достичь этого, но, вероятно, разумнее просто изменить, например,

[self doCostlyTask];

Кому:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^()
{
    [self doCostlyTask];

    dispatch_async(dispatch_get_main_queue(), ^()
    {
        // most UIKit tasks are permissible only from the main queue or thread,
        // so if you want to update an UI as a result of the completed action,
        // this is a safe way to proceed
        [self costlyTaskIsFinished];
    });
});

Это, по сути, говорит ОС: «делайте этот код с низким приоритетом там, где это будет наиболее эффективно». Различные вещи, которые вы публикуете в любой из глобальных очередей, могут или не могут выполняться в том же потоке, что и другие, и в качестве потока, который их отправил, и могут или не могут происходить одновременно. ОС применяет правила, которые она считает оптимальными.

Экспозиция:

GCD - это реализация Apple пула потоков, и они в то же время представили замыкания (как «блоки»), чтобы сделать его пригодным для использования. Таким образом, синтаксис ^(C-style args){code} является блоком / закрытием. То есть это код плюс состояние любых переменных (подлежащих предупреждению), на которые ссылается код. Вы можете хранить и вызывать блоки самостоятельно без знания или использования GCD.

dispatch_async - функция GCD выдает блок в назначенную очередь. Он выполняет блок в некотором потоке в некоторое время и применяет неуказанные внутренние правила, чтобы сделать это оптимальным образом. Он будет судить по таким факторам, как количество ядер, которые у вас есть, насколько они заняты, что они в данный момент думают об энергосбережении (которое может зависеть от источника питания), как работают энергопотребление для конкретного процессора и т. Д.

Итак, когда программист разрабатывается, блоки превращают код в нечто, что вы можете передать в качестве аргумента. GCD позволяет вам запрашивать, чтобы блоки выполнялись в соответствии с наилучшим планированием, которым может управлять ОС. Блоки очень легкие для создания и копирования - намного больше, чем, например, NSOperation s.

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

4 голосов
/ 14 ноября 2011

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

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

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

Это осложняется большим количеством путей достижения параллелизм, который, кажется, возник за эти годы. (Явный NSThreads, NSOperationQueue, GCD и т. Д.)

NSOperationQueue использует GCD , так что вы можете использовать это, если это облегчает жизнь, чем использование GCD напрямую.

Использовать GCD и предположить, что он умнее, чем я, по поводу использования (повторного) потока?

Точно.

1 голос
/ 14 ноября 2011

Я бы использовал NSOperationQueue или GCD и профиль.Не могу себе представить, что накладные расходы потока побьют сетевые задержки.

NSOperationQueue позволит вам ограничить количество одновременных операций, если они в конечном итоге станут слишком жадными.На самом деле, вы можете ограничить его одним, если вам нужно.

...