zoukankan      html  css  js  c++  java
  • runloop

    何时使用 Run Loop?

    仅当在为你的程序创建辅助线程的时候,你才需要显式运行一个 run loop。Run loop 是程序主线程基础设施的关键部分。所以,Cocoa 和 Carbon 程序提供了代码运 行主程序的循环并自动启动 run loop。IOS 程序中 UIApplication 的 run 方法(或 Mac OS X 中的 NSApplication)作为程序启动步骤的一部分,它在程序正常启动的时 候就会启动程序的主循环。类似的,RunApplicationEventLoop 函数为 Carbon 程序 启动主循环。如果你使用 xcode 提供的模板创建你的程序,那你永远不需要自己去显 式的调用这些例程。

    对于辅助线程,你需要判断一个 run loop 是否是必须的。如果是必须的,那么 你要自己配置并启动它。你不需要在任何情况下都去启动一个线程的 run loop。比 如,你使用线程来处理一个预先定义的长时间运行的任务时,你应该避免启动 run loop。Run loop 在你要和线程有更多的交互时才需要,比如以下情况:

     使用端口或自定义输入源来和其他线程通信  使用线程的定时器  Cocoa 中使用任何 performSelector...的方法  使线程周期性工作

     

    如果你决定在程序中使用 run loop,那么它的配置和启动都很简单。和所有线程 编程一样,你需要计划好在辅助线程退出线程的情形。让线程自然退出往往比强制关 闭它更好。关于更多介绍如何配置和退出一个 run loop,参阅”使用 Run Loop 对象” 的介绍。

     

    作用

    • 使程序一直运行并接收用户的输入
    • 决定程序在何时处理哪些事件
    • 调用解耦(Message Queue)
    • 节省CPU时间(当程序启动后,什么都没有执行的话,就不用让CPU来消耗资源来执行,直接进入睡眠状态)

    模式

    • RunLoop 在同一段时间只能且必须在一种特定的模式下运行
    • 如果要更换 Mode,必须先停止当前的 Loop,然后再重新启动 Loop
    • Mode 是保证滚动流畅的关键

    • NSDefaultRunLoopMode:默认状态、空闲状态

    • UITrackingRunLoopMode:滚动模式
    • UIInitializationRunLoopMode:私有的,App启动时
    • NSRunLoopCommonModes:默认包含1,2两种模式

    模拟 RunLoop 实现

    void runEvent(int num){
        if (num == 1){
            NSLog(@"按钮点击事件");
        }
    
        if (num == 2) {
            NSLog(@"scrollView拖动事件");
        }
    
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            //NSLog(@"Hello, World!");
    
            while (YES) {
                NSLog(@"请输入选择项,0表示退出");
    
                int num =0;
    
                scanf("%d",&num);
    
                if (num==0) {
                    break;
                }else{
                    runEvent(num);
                }
            }
        }
        return 0;
    }
    

    运行循环与时钟

    @interface ViewController ()
    
    @property(nonatomic,strong)NSTimer *timer;
    
    @property(nonatomic,assign)int count;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(demo) userInfo:nil repeats:YES];
    
        //需要将其加入到运行循环里面才能执行
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    }
    
    - (void)demo{
        self.count++;
    
        NSLog(@"hello===%d",self.count);
    }
    
    • 将时钟添加到其他线程工作
    @interface ViewController ()
    
    @property(nonatomic,strong)NSTimer *timer;
    
    @property(nonatomic,assign)int count;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        //1.创建一个子线程
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun) object:nil];
    
        [thread start];
    }
    
    /**
     1.在子线程中,如下事件是不会开启的
    
     1.定时源事件
     2.输入源事件
     3.网络下载
     */
    - (void)threadRun{
        NSLog(@"%s",__func__);
    
        self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(demo) userInfo:nil repeats:YES];
    
        //需要将其加入到运行循环里面才能执行
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    
        //1.需要我们自己手工开启我们子线程的NSRunLoop
        CFRunLoopRun();
    }
    
    - (void)demo{
    
        self.count++;
    
        if (self.count==5) {
            NSLog(@"---停止子线程运行循环---");
    
            //停止运行循环,这样子线程才能销毁
            CFRunLoopStop(CFRunLoopGetCurrent());
        }
    
        NSLog(@"hello===%d",self.count);
    }
    

    注意:主线程的运行循环是默认启动的,但是子线程的运行循环是默认不工作的,子线程的运行循环需要我们自己手工开启和关闭,只有自己手工关闭,这样才能够保证线程执行完毕后,子线程自动被销毁

  • 相关阅读:
    在线报表设计实战系列 – 制作动态列与静态列混排的报表(5)
    在线报表设计实战系列 – 制作复杂表头报表(4)
    在线报表设计实战系列 – 制作交叉分析表(3)
    在线报表设计实战系列 – 制作表格类报表(2)
    在线报表设计实战系列 – 准备数据源(1)
    ActiveReports 报表控件V12新特性 -- RPX报表转换为RDL报表
    ActiveReports 报表控件V12新特性 -- 新增矩表的RepeatToFill属性
    HDU 2199 Can you solve this equation?_二分搜索
    POJ 1606 jugs(又是水壶问题)
    POJ 3414 Pots
  • 原文地址:https://www.cnblogs.com/donghaoios/p/5089716.html
Copyright © 2011-2022 走看看