NSRunLoops в какао?


Допустим, у меня есть 2 потока, один-основной поток, а другой-вторичный поток. Основной поток используется больше всего, но иногда (редко) я хочу, чтобы вторичный поток выполнял некоторую работу, основанную на вызовах из основного потока. Большую часть времени вторичная нить должна спать. Теперь, после некоторого поиска, я понимаю, что способ сделать это-использовать runLoops. Поэтому я попытался прочитать документы apple (http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW5)

Но мне кажется, что это очень сложно,и я испытываю некоторые трудности. Существует ли элегантный и простой способ достичь того, что я описал? Есть ли подобные примеры кода runLoop, с которыми я могу работать и играть?

Спасибо

3 2

3 ответа:

У Мэтта Галлахера есть хорошая статья в блоге, в которой он сравнивает подход вторичного потока с другими способами выполнения фоновой работы.

Http://cocoawithlove.com/2010/09/overhead-of-spawning-threads.html

В вашем случае вам не нужно беспокоиться о накладных расходах на создание потоков. Но примеры кода Мэтта могут дать некоторое представление об управлении runloop вторичного потока.

Все, что было сказано, я бы пошел с Советом Джошуа и просто использовал NSOperationQueue и NSOperation, чтобы сделать фоновую работу. Если работа может быть инкапсулирована в NSInvocation, можно использовать NSInvocationOperation и избежать подкласса NSOperation.

Это звучит как раз то, для чего была создана NSOperation/NSOperationQueue. Если у вас есть только случайные "единицы работы", почему бы не сделать их операцией, а затем следить за ее завершением и соответствующим образом обновлять пользовательский интерфейс?

Каждый поток имеет цикл выполнения.

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

  • таймеры есть.
  • Обычно они ждут, пока что-то постучится в порт ядра Mach или файловый дескриптор.

Когда цикл выполнения выполняется, он обычно не выполняется-то есть поток спит, а не потребляет любые циклы процессора. (Если вы попробуете его, то обнаружите, что процесс застрял в mach_msg_trap. Это системный вызов" подождите, пока что-то произойдет".) Ядро пробуждает поток (который, таким образом, возвращается из mach_msg_trap), когда происходит что-то, о чем должен позаботиться цикл выполнения потока.

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

Тем не менее, NSOperation почти наверняка является лучшим решением, поскольку он предназначен для случая, который вы описали: дискретные единицы работы, которые должны выполняться последовательно, до N (которые вы выбираете и по крайней мере 1) за один раз. Обратите внимание, что NSOperationQueue повторно использует потоки, поэтому он не обязательно создает новый поток для каждой операции. Действительно, не делать этого-часть смысла: он создает потоки лениво и использует любые, которые уже есть есть, которые ничего не делают.