Держите NSThread в живых и запустите NSRunLoop на нем
поэтому я начинаю новый NSThread, который я хочу использовать позже, позвонив performSelector:onThread:...
. Из того, как я понимаю, он вызывает, что методы добавляют этот вызов в runloop в этом потоке, поэтому на следующей итерации он будет всплывать все эти вызовы и впоследствии вызывать их, пока не останется ничего, чтобы вызвать. Поэтому мне нужна такая функциональность, простой поток, готовый к работе, который я просто могу вызвать. Мой текущий код выглядит так:
- (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];
}
но поток не сохраняется живой, и performSelector: 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