我是程序员;您好程先生;叫我序员就好了

RunLoop入门

2015-01-04  本文已影响0人  pp_panda

       之前在使用NSTimer时,遇到一个问题,NSTimer启动了,但是只会出现一次定时,之后就不起作用。问了同事,他说需要加在RunLoop中,我没有考虑太多,就听他说的,在外层加了一个Runloop,定时器确实起作用了。近期做另一个任务,发现RunLoop在多线程中用的比较多,所以大概查了下相关资料。

      runLoop是线程中的循环,并对收到的事件进行处理,它从两个不同的事件源中接收消息。Input sources(CFRunLoopSource)投递异步消息,通常来源于另一个thread或者另一个应用程序。Timer sources(CFRunLoopTimer)当在计划的时间或重复的时间间隔内投递同步消息。两种事件源都使用应用程序指定的处理方式对到达的事件进行处理。下图展示了run loop和不同的事件源结构:

Run Loop的使用场合:

 1. 使用port或是自定义的input source来和其他线程进行通信                                          2. 在线程(非主线程)中使用timer                                                                            3. 使用 performSelector…系列(如performSelectorOnThread, …)                          4. 使用线程执行周期性工作

run loop不需要创建,在线程中只需要调用[NSRunLoop currentRunLoop]就可以得到假设我们想要等待某个异步方法的回调。比如connection。如果我们的线程中没有启动run loop,是不会有效果的(因为线程已经运行完毕,正常退出了)。                                  使用runLoop阻塞线程的正确写法                                                        @implementation ViewController                                                                              {                                                                                                                                      BOOL end;                                                                                                          }

– (void)viewDidLoad                                                                                                 {                                                                                                                                      [super viewDidLoad];                                                                                                NSLog(@”start new thread …”);                                                                                  [NSThread detachNewThreadSelector:@selector(runOnNewThread)                          toTarget:self withObject:nil];                                                                                    while (!end) {                                                                                                            NSLog(@”runloop…”);                                                                                                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:         [NSDate distantFuture]];                                                                                           NSLog(@”runloop end.”);                                                                                           }                                                                                                                               NSLog(@”ok.”);                                                                                                   }

-(void)runOnNewThread                                                                                          {                                                                                                                                     NSLog(@”run for new thread …”);                                                                             sleep(1);                                                                                                                   [self performSelectorOnMainThread:@selector(setEnd) withObject:nil                       waitUntilDone:NO];                                                                                                 NSLog(@”end.”);                                                                                                 }

-(void)setEnd  {                                                                                                               end=YES;                                                                                                           }

每次运行 Run loop,你线程的 Run loop 对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:

1. 通知观察者 Run loop 已经启动。

2. 通知观察者任何即将要开始的定时器。

3. 通知观察者任何即将启动的非基于端口的源。

4. 启动任何准备好的非基于端口的源。

5. 如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤 9。

6. 通知观察者线程进入休眠。

7. 将线程置于休眠直到任一下面的事件发生:

   某一事件到达基于端口的源;

   定时器启动;

   Run loop 设置的时间已经超时;

   Run loop 被显式唤醒。

8. 通知观察者线程将被唤醒。

9. 处理未处理的事件

    如果用户定义的定时器启动,处理定时器事件并重启 Run loop。进入步骤 2。

    如果输入源启动,传递相应的消息。

    如果 Run loop 被显式唤醒而且时间还没超时,重启 Run loop,进入步骤 2。

10. 通知观察者 Run loop 结束。

上一篇 下一篇

猜你喜欢

热点阅读