Понимание NSRunLoop

может ли кто-нибудь объяснить, что такое NSRunLoop? так как я знаю NSRunLoop - Это что-то связанное с NSThread верно? Предположим, я создаю поток как

NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];

-(void) someMethod
{
    NSLog(@"operation");
}

Итак, после того, как этот поток закончит свою работу правильно? зачем использовать RunLoops или где использовать ? из Apple docs я прочитал что-то, но это не ясно для меня, поэтому, пожалуйста, объясните как можно проще

4 ответов


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

каждый NSThread имеет свой собственный цикл выполнения, к которому можно получить доступ с помощью метода currentRunLoop.

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

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

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

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

редактировать

попытка обратиться к комментарию. Я разбил его на куски.

  • это означает, что я могу только открыть/запустить, чтобы запустить цикл внутри потока правильно?

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

  • есть ли простой пример как добавить событие на запуск петля?

Если вы хотите контролировать порт, вы просто добавите этот порт в цикл выполнения, а затем цикл выполнения будет следить за этим портом для активности.

- (void)addPort:(NSPort *)aPort forMode:(NSString *)mode

вы также можете добавить таймер явно с

- (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode
  • что означает, что он вернется к своему циклу?

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

  • цикл запуска неактивен при запуске потока?

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

  • можно ли добавить некоторые события в цикл выполнения потока вне нити?

Я не уверен, что вы подразумеваете здесь. События не добавляются в цикл выполнения. Вы добавляете источники ввода и источники таймера (из потока, которому принадлежит цикл выполнения). Затем цикл выполнения отслеживает их активность. Конечно, можно обеспечить ввод данных из других потоков и процессов, но ввод будет обрабатываться циклом выполнения, который отслеживает эти источники в потоке, выполняющем цикл выполнения.

  • означает ли это, что иногда я могу использовать цикл запуска для блокировки потока на время

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

то же самое относится к любой петля.

Я предлагаю вам прочитать следующую документацию на выполнения петли:

https://developer.apple.com/documentation/foundation/nsrunloop

и как они используются в рамках темы:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1


Runloops немного похожи на коробку, где все просто происходит.

в основном в Runloop вы идете обрабатывать некоторые события, а затем возвращаетесь. Или возврат, если он не обрабатывает какие-либо события до истечения тайм-аута. Вы можете сказать, что это похоже на асинхронные NSURLConnections, обработка данных в фоновом режиме, не мешая вашему текущему циклу, и в то же время вам нужны данные синхронно. Что можно сделать с помощью Runloop, которые удерживают ваш асинхронный NSURLConnection и предоставлять данные во время вызова. Вы можете использовать Runloop следующим образом :-

NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.1];
while (YourBoolFlag && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:loopUntil])
loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.1];

в этом Runloop он будет работать, пока вы не завершите некоторые из ваших других работ и не установите YourBoolFlag to false.

аналогично вы можете использовать их в потоках.

надеюсь, это поможет вам.


циклы выполнения-это то, что отделяет интерактивные приложения с инструменты.

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

С здесь

они позволяют вам ждать, пока пользователь нажмите и ответьте соответственно, подождите, пока вы получите completionHandler и примените его результаты, подождите, пока вы получите таймер и выполните функцию. Если у вас нет runloop, вы не можете слушать/ждать пользовательских нажатий, вы не можете ждать, пока произойдет сетевой вызов, вы не можете быть разбужены за x минут.

и с комментарий:

фоновые потоки не имеют собственных runloops, но вы можете просто добавить один. Е. Г. AFNetworking 2.x сделал это. Это была испытанная и истинная техника для NSURLConnection или NSTimer в фоновых потоках, но мы этого не делаем мы гораздо больше, так как новые API устраняют необходимость делать это. Но похоже, что URLSession делает, например,вот простой запрос, работающего [см. левую панель изображения] обработчики завершения в главной очереди, и вы можете видеть, что он имеет запуск петля На фоновом потоке


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

отсюда


наиболее важной особенностью CFRunLoop является CFRunLoopModes. CFRunLoop работает с системой "Run Loop Sources". Источники регистрируются в цикле выполнения для одного или нескольких режимов, а сам цикл выполнения выполняется в заданном режиме. Когда событие поступает в источник, оно обрабатывается циклом выполнения, только если исходный режим соответствует текущему режиму цикла выполнения.

отсюда