【问题标题】:What does NSRunLoop do?NSRunLoop 是做什么的?
【发布时间】:2013-05-10 07:45:20
【问题描述】:

我读过很多关于NSRunLoop 的帖子,比如thisthisthis。但是不知道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之外什么都没有?

【问题讨论】:

  • 我认为它是一个花哨的 while(true){ //insert job to be done here } ,您可以在其中动态添加要执行的代码(事件、工作、套接字等)。 runloop 并不是真正的空,一个端口已经附加到 runloop,它是一种进程间通信的形式。
  • 我发现这个bou.io/RunRunLoopRun.html 也很有用

标签: ios port nsthread nsrunloop


【解决方案1】:

您展示的示例是一个 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) 那么为什么threadProc里面有while循环呢? 2) GCD 会将工作转移到任何可用/未知的线程,但 NSRunLoop 会确保所有工作都转移到同一个工作线程,对吧?
  • 提供一种终止运行循环的机制 - 当设置标志 isStopped 时(尽管代码中没有显示...)
  • 2) 查看针对您所描述的用例的 GCD 方法的编辑答案。
  • dispatch_queue 是否确保 2 个工作将在同一个线程中串行完成?
  • @onmyway133 没有串行队列不能保证所有块都将在同一个线程中完成。它只保证串行执行
【解决方案2】:

幕后发生了很多事情。这样做的原因是它为线程在没有工作项时停止执行提供了一种方法。如果您曾经使用过实时操作系统,那么任务需要一个地方来放弃处理器,以便其他人可以运行。

没有充分记录的是,当您发送 performSelector:onThread:... 时,运行循环将消息排队并唤醒以让线程处理它。如果您将日志消息添加到 while 循环中,您会看到这种情况发生。

对于真正好奇的人,github 上提供了示例代码,您可以尝试使用运行循环 - 添加评论,我会列出一些。

【讨论】:

  • 1) 但是在threadProc内部,有一个while循环,所以线程会一直忙? NSRunLoop 如何告诉它停止执行? 2) AFAIK,这是一种确保许多对 performSelector:onThread: 的调用将工作转移到同一个工作线程的机制,对吧?
  • 1) 抱歉不清楚 - 如果您的代码没有要处理的内容,操作系统将暂停运行模式中的线程。 2)它是系统的一个特性——但还有其他特性——端口和定时器处理。通过阅读 CFRunloop 上的苹果文档,您将学到最多 - 我相信它有一个指南。
猜你喜欢
  • 1970-01-01
  • 2010-11-10
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 2011-11-01
相关资源
最近更新 更多