保持NSThread存活并在其上运行NSRunLoop

时间:2011-06-08 00:22:54

标签: objective-c cocoa nsthread foundation 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 个答案:

答案 0 :(得分:15)

运行循环需要至少运行一个“输入源”。主运行循环可以,但您必须手动添加源以获取辅助运行循环的-run方法来执行任何操作。有关此here的一些文档。

让这个工作起来的一种天真的方法就是将[[NSRunLoop currentRunLoop] run]置于无限循环中;当有事情要做时,它会做,然后立即返回。问题是该线程将花费相当多的处理器时间,只需等待某些事情发生。

另一个解决方案是在此运行循环上安装NSTimer以使其保持活动状态。

但是,如果可能的话,你应该使用专为这类事情设计的机制。如果可能,您可能希望使用NSOperationQueue进行后台操作。

答案 1 :(得分:8)

这段代码应该强制线程永远等待

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