• iOS运行回路(RunLoop)总结


     

    首先看两个runloop的示例,来源:http://paste.lisp.org/display/86524

    第一个:

     

    1. #include <CoreFoundation/CoreFoundation.h>  
    2.   
    3. static void  
    4. _perform(void *info __unused)  
    5. {  
    6.     printf("hello\n");  
    7. }  
    8.   
    9. static void  
    10. _timer(CFRunLoopTimerRef timer __unused, void *info)  
    11. {  
    12.     CFRunLoopSourceSignal(info);  
    13. }  
    14.   
    15. int  
    16. main()  
    17. {  
    18.     CFRunLoopSourceRef source;  
    19.     CFRunLoopSourceContext source_context;  
    20.     CFRunLoopTimerRef timer;  
    21.     CFRunLoopTimerContext timer_context;  
    22.   
    23.     bzero(&source_context, sizeof(source_context));  
    24.     source_context.perform = _perform;  
    25.     source = CFRunLoopSourceCreate(NULL, 0, &source_context);  
    26.     CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);  
    27.   
    28.     bzero(&timer_context, sizeof(timer_context));  
    29.     timer_context.info = source;  
    30.     timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 1, 0, 0, 
    31.     _timer, &timer_context);  
    32.     CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes);  
    33.   
    34.     CFRunLoopRun();  
    35.   
    36.     return 0;  
    37. }  

     

    第二个:

     

    1. #include <dispatch/dispatch.h>  
    2. #include <stdio.h>  
    3.   
    4. int  
    5. main()  
    6. {  
    7.     dispatch_source_t source, timer;  
    8.   
    9.     source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0,
    10.     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));  
    11.     dispatch_source_set_event_handler(source, ^{  
    12.         printf("hello\n");  
    13.     });  
    14.     dispatch_resume(source);  
    15.   
    16.     timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, 
    17.     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));  
    18.     dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC, 0);  
    19.     dispatch_source_set_event_handler(timer, ^{  
    20.         dispatch_source_merge_data(source, 1);  
    21.     });  
    22.     dispatch_resume(timer);  
    23.   
    24.     dispatch_main();  
    25. }  

     

    功 能是向main线程中加入两个input source,一个是timer,一个是自定义input source,然后这个timer中触发自定义source,于是调用其回调方法。 在这儿timer触发source来调用回调方法,显得有点多此一举。但是在多线程开发当中,这就很有用了,我们可以把这个自定义的source加入到子 线程的runloop中,然后在主线程中触发source,这样在子线程中就可以调用回调方法了。  这样做的好久是什么呀? 节约用电,因为runloop一般情况下是休眠的,只有事件触发的时候才开始工作。 这与windows下的waitforsingleobject有点类似, 与多线程中的信号量,事件也有些雷同。

     

    上 面说到的input source(输入源例)到底是什么呢?输入源样例可能包括用户输入设备(如点击button)、网络链接(socket收到数据)、定期或时间延迟事件 (NSTimer),还有异步回调(NSURLConnection的异步请求)。然后我们对其进行了分类,有三类可以被runloop监控,分别是 sources、timers、observers。

    在苹果文档中对runloop有详细介绍,下面参考中有中文版。那文档中的代码关于NSPort的部份在iOS上是不行的,不过可以用其CF方法实现,在我的demo中有展示。

     

    每一个线程都有自己的runloop, 主线程是默认开启的,创建的子线程要手动开启,因为NSApplication 只启动main applicaiton thread。

    没有source的runloop会自动结束。

    事件由NSRunLoop 类处理。

    RunLoop监视操作系统的输入源,如果没有事件数据, 不消耗任何CPU 资源。

    如果有事件数据,run loop 就发送消息,通知各个对象。

    用 currentRunLoop 获得 runloop的 reference

    给 runloop 发送run 消息启动它。

     

     

    文档中介绍下面四种情况是使用runloop场合:

     1.使用端口或自定义输入源和其他线程通信

     2.子线程中使用了定时器

     3.cocoa中使用任何performSelector到了线程中运行方法

     4.使线程履行周期性任务,(我把这个理解与2相同)

    如果我们在子线程中用了NSURLConnection异步请求,那也需要用到runloop,不然线程退出了,相应的delegate方法就不能触发。

    解决的方法参看:

    http://www.cocoabyss.com/foundation/nsurlconnection-synchronous-asynchronous/

    http://www.wim.me/nsurlconnection-in-its-own-thread/

     

    参考:

    http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

    http://www.wim.me/nsurlconnection-in-its-own-thread/

    http://xubenyang.me/384

    http://iphonedevelopmentbits.com/event-driven-multitasking-runloopssymbian-ios

  • 相关阅读:
    所有问题都可以通过增加一层来解决
    open一个页面并关闭父页(小技巧)
    <%=字符串%>回刷技巧(小技巧)
    轮环(Ouroboros)世界观介绍,摘自Guide Book
    windows7下MSN如何最小化到任务栏
    触发器权限
    网页GZIP压缩
    iis6配置使用页面Gzip压缩提速
    唉,被删的帖
    创建型模式,结构型模式,结构型模式
  • 原文地址:https://www.cnblogs.com/zhangjie/p/3071074.html
Copyright © 2020-2023  润新知