Поддержите NSThread и запустите на нем NSRunLoop

Итак, я запускаю новый NSThread, который хочу использовать позже, вызывая performSelector:onThread:..., Насколько я понимаю, вызов этого метода добавляет этот вызов к циклу выполнения в этом потоке, поэтому на следующей итерации он извлекает все эти вызовы и впоследствии вызывает их до тех пор, пока не останется ничего для вызова. Поэтому мне нужна такая функциональность, готовая к работе пустая нить, которую я могу просто вызвать. Мой текущий код выглядит так:

   - (void)doInitialize
   {
       mThread =  [[NSThread alloc] initWithTarget:self selector:@selector(runThread) object:nil];
       [mthread start];
   }

   - (void)runThread
   {
       NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];

       // From what I understand from the Google machine is that this call should start the
       // runloop on this thread, but it DOESN'T. The thread dies and is un-callable
       [[NSRunLoop currentRunLoop] run];

       [pool drain];
   }

   - (void)scheduleSomethingOnThread
   {
       [self performSelector:@selector(hardWork) onThread:mThread withObject:nil waitUntilDone:NO];
   }

Но поток не сохраняется, и executeSelector: onThread ничего не делает. Как мне поступить правильно?

2 ответа

Решение

Для запуска цикла требуется как минимум один "источник ввода". Основной цикл выполнения делает, но вы должны добавить источник вручную, чтобы получить дополнительный цикл выполнения -run способ сделать что-нибудь. Здесь есть некоторая документация по этому вопросу.

Один наивный способ заставить это работать - просто поставить [[NSRunLoop currentRunLoop] run] в бесконечном цикле; когда есть что-то сделать, он сделает это и немедленно вернется в противном случае. Проблема в том, что поток займет приличное количество процессорного времени, просто ожидая, что что-то произойдет.

Другое решение состоит в том, чтобы установить NSTimer в этом цикле выполнения, чтобы сохранить его работоспособным.

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

Этот кусок кода должен заставить поток ждать вечно

BOOL shouldKeepRunning = YES;        // global
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; // adding some input source, that is required for runLoop to runing
while (shouldKeepRunning && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); // starting infinite loop which can be stopped by changing the shouldKeepRunning's value
Другие вопросы по тегам