木先生

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

这篇总结懒得写了,直接转了网上的一篇文章:http://blog.csdn.net/favormm/article/details/6928432

首先看两个runloop的示例,来源: http://paste.lisp.org/display/86524 第一个: #includeCoreFoundation/CoreFoundation.h static void _perform( void *info__unused) { printf( hello\n ); } static void _timer(CFRunLoopTimerReftimer_

原文:http://blog.csdn.net/favormm/article/details/6928432


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

第一个:

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

第二个:

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

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

 

至此,oc语言部分的总结就写完了。后面该开始学习iphone SDK方面的学习了。到目前为止,虽然对语言有了一知半解,但是依旧还什么都不会做,属于幼儿班前儿童:)

posted on 2012-03-15 17:09  一十一王  阅读(1459)  评论(0编辑  收藏  举报