我阅读了很多关于NSRunLoop
的帖子,例如this,this,this。但无法弄清楚NSRunLoop
实际上做了什么
我通常看到的是工作线程
wthread = [[NSThread alloc] initWithTarget:self selector:@selector(threadProc) object:nil];
[wthread start];
里面有一个NSRunLoop
- (void)threadProc
{
NSAutoreleasePool* pool1 = [[NSAutoreleasePool alloc] init];
BOOL isStopped = NO;
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
while (!isStopped)
{
{
NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init];
[runloop runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
[pool2 release];
}
}
[pool1 release];
}
主线程将一些工作传递给了这个wthread
[self performSelector:@selector(someWork:) onThread:wthread withObject:nil waitUntilDone:NO];
在将工作从主线程传递给工作线程方面,我看到很多人这样做。为什么需要NSRunLoop?它做了什么?
我读到NSRunLoop
用于管理事件,除了在threadProc
内调用 runMode 之外什么都没有?
答案 0 :(得分:5)
您展示的示例是一个Cocoa习惯用法,用于创建一个在方法-threadProc
退出后将继续运行的线程。为什么?
由于:
NSRunLoop
个实例至少有一个输入源([NSMachPort port]
)runMode:beforeDate
如果不添加输入源并显式启动运行循环,则线程将终止。
顺便说一下,虽然运行循环对于管理事件和某些异步任务仍然至关重要,但我不会将NSThread
视为现在在Cocoa应用程序中构建大多数异步工作的默认方式。 GCD是一种更清晰的封装背景工作的方式。
修改强>:
将工作提交到GCD中的串行队列:
@interface Foo : NSObject
@end
@implementation Foo {
dispatch_queue_t _someWorkerQueue;
}
- (id)init {
self = [super init];
if( !self ) return nil;
_someWorkerQueue = dispatch_queue_create("com.company.MyWorkerQueue", 0);
return self;
}
- (void)performJob {
dispatch_async(_someWorkerQueue, ^{
//do some work asynchronously here
});
dispatch_async(_someWorkerQueue, ^{
//more asynchronous work here
});
}
@end
答案 1 :(得分:4)
幕后发生了很多事情。这样做的原因是它提供了一种在没有工作项时线程停止执行的方法。如果你曾经使用过实时操作系统,任务需要一个放弃处理器的地方,以便其他人可以运行。
没有详细记录的是当你发送performSelector:onThread:...时,它是对消息进行排队的唤醒循环,让线程处理它。如果您将日志消息添加到while循环,您可以看到这种情况发生。
对于真正好奇的github上的示例代码,您可以使用运行循环 - 添加注释,我会列出一些。