В чем основная разница между NSTimer, NSTask, NSThread и NSRunloop? - PullRequest
27 голосов
/ 14 июля 2009

В чем разница между NSTimer, NSTask, NSThread и NSRunloop и существует ли руководство по использованию каждого из них?

Ответы [ 3 ]

43 голосов
/ 14 июля 2009

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

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

[РЕДАКТИРОВАТЬ: см. Комментарии для более подробного обсуждения пулов autorelease. Важно помнить, что новые потоки должны заботиться о настройке пула автоматического выпуска. Например, методы, которые вызываются с detachNewThreadSelector (см. Ниже), должны иметь следующую первую и последнюю строки:

   NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ];
   [code here]
   [pool release];

То же самое относится к потокам, порожденным другими методами.]

В главном потоке , где выполняется вся обработка пользовательского интерфейса, цикл выполнения очень важен, поскольку он поддерживает интерфейс реактивным. Вот почему вы никогда не должны запускать код, который занимает много времени в главном потоке: он будет постоянно поглощать поток, и цикл выполнения не сможет запускаться достаточно часто, что приведет к блокировке или медленному интерфейсу. Если вам нужно выполнить трудоемкие вычисления или оставить задачу в фоновом режиме, вам следует создать новый поток. Опять же, вам, вероятно, не нужно думать о создании нового цикла выполнения. Простой способ выполнения метода в новом потоке:

[NSThread detachNewThreadSelector:@selector(theSelector) toTarget:self withObject:nil];

Межпотоковое взаимодействие может быть сложным, и вы должны знать методы performSelector:onThread:withObject:waitUntilDone: и performSelectorOnMainThread:withObject:waitUntilDone: (Хорошие советы по отправке уведомлений NSN по всем темам здесь .)

Таймеры также обрабатываются циклами выполнения. В отличие от циклов выполнения, вы, вероятно, часто используете таймеры непосредственно в вашей программе. Самый простой способ создания таймера:

[self performSelector:@selector(aSelector) withObject:nil afterDelay:1.0];

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

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

Вы отметили свой вопрос как «iphone», и на iPhone вы никогда не будете использовать NSTasks.

NSOperations используются, когда вам нужно обрабатывать большее количество различных задач, помещая их в очереди и / или обрабатывая их в отдельных потоках (хотя они не имеют для запустить в отдельных темах). Если вашему приложению нужно создать всего несколько специализированных потоков, то нет смысла использовать класс NSOperation. Но если вы будете регулярно генерировать задачи (например, связь с сервером), которые необходимо отслеживать, NSOperation и NSOperationQueue пригодятся.

4 голосов
/ 14 июля 2009
  • NSTimer - это объект таймера, способ вызвать селектор для объекта в будущем.
  • NSThread является классом потока. Я полагаю, вы знаете, что это за нить.
  • NSTask - это класс процесса, способ запуска другой программы из вашей программы.
  • NSOperation (я добавляю к вопросу) - очень хорошая абстракция для одной задачи. Вы встраиваете свою операцию в этот класс и можете легко выполнять ее одновременно с помощью класса NSOperationQueue.
  • NSRunLoop является самым трудным для понимания. Каким-то образом абстрагирует и адаптирует системный вызов select() unix, управляя источниками ввода и отправляя события и таймеры в потоке.

Руководством является Руководство по программированию Apple Threading .

3 голосов
/ 14 июля 2009

Другие ответы довольно неплохо суммируют таймеры, задачи и потоки. Я хотел бы прокомментировать немного больше о NSRunloop, так как я думаю, что большинство других ответов все еще оставляют некоторую путаницу. Из документации NSRunloop:

Объект NSRunLoop обрабатывает ввод для источников, таких как мышь и клавиатура события из оконной системы, NSPort объекты и объекты NSConnection. Объект NSRunLoop также обрабатывает События NSTimer.

также

В общем, ваше приложение не нужно либо создать, либо явно управлять объектами NSRunLoop. каждый NSThread объект, в том числе основной поток приложения, имеет NSRunLoop объект автоматически создается для этого по мере необходимости. Если вам нужно получить доступ к циклу выполнения текущего потока, вы делаете это с помощью метода класса currentRunLoop.

Думайте о NSRunloop как о главном цикле обработки и диспетчеризации событий для определенного потока. Он считывает данные с устройств ввода, обслуживает любые объекты, которые необходимо обслуживать, и соответствующим образом отправляет данные.

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