iOS运行回路(RunLoop)总结

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

第一个:

#include <CoreFoundation/CoreFoundation.h> static void _perform(void *info __unused) { printf("hello\n"); } static void _timer(CFRunLoopTimerRef timer __unused, void *info) { CFRunLoopSourceSignal(info); } int main() { CFRunLoopSourceRef source; CFRunLoopSourceContext source_context; CFRunLoopTimerRef timer; CFRunLoopTimerContext timer_context; bzero(&source_context, sizeof(source_context)); source_context.perform = _perform; source = CFRunLoopSourceCreate(NULL, 0, &source_context); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); bzero(&timer_context, sizeof(timer_context)); timer_context.info = source; timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 1, 0, 0, _timer, &timer_context); CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes); CFRunLoopRun(); return 0; }

第二个:

#include <dispatch/dispatch.h> #include <stdio.h> int main() { dispatch_source_t source, timer; source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); dispatch_source_set_event_handler(source, ^{ printf("hello\n"); }); dispatch_resume(source); timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC, 0); dispatch_source_set_event_handler(timer, ^{ dispatch_source_merge_data(source, 1); }); dispatch_resume(timer); dispatch_main(); }


功能是向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/


具体参看demo.


参考:

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











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Runloop的工作:如何管理事件/消息,如何让线程在没有处理消息时休眠以避免资源占用、在有消息到来时立刻被唤醒。 Osx/ios提供了两种runloop对象 : CFRunLoopRef是在CoreFoundation框架呢,是纯C函数的API,是线程安全的 NSRunLoop是基于CFRunLoopRef的封装,不是线程安全 CFRunLoopRef的线程安全性:CFRunLoopRef不是在线程刚创建的时候创建的,而是在线程获取的时候创建的,如果不主动获取线程,一直不会有。CFRunLoopRef在创建时通过static CFSpinLock_t loopsLock锁住CFRunLoopRef对象,所以CFRunLoopRef是安全的。 一个runloop包含若干个mode。每个mode又包含若干个Source/Timer/Observer CFRunLoopSourceRef是事件产生的地方。Source有两个版本: Source0和Source1。 Source0只包含一个回调,它不能主动出发事件,需要调用CFRunLoopSOurceSignal(source)将source标记,然后手动调用CFRunloopWakeUp()来唤醒RunLoop Source1包含了一个mach_port和一个回调,被用于通过内核和其他线程来发送消息,这种source能主动唤醒runloop。 CFRunLoopTimerRef是基于时间的触发器,它和NSTimer是toll-free bridged的,可以混用,包含一个时间长度和一个回调。当其加入到RunLoop时,RunLoop会注册对应的时间点,当时间点到时,RunLoop会被唤醒执行回调。 CFRunLoopObserverRef是观察者,每个Observer都包含了一个回调,当RunLoop的状态发生变化时,观察者就能通过回调接受到这个变化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值