美文网首页
『ios』GCD补习 dispatch block

『ios』GCD补习 dispatch block

作者: butterflyer | 来源:发表于2018-10-30 16:58 被阅读13次
    image.png

    不要走的太快,慢慢来。

    这几天翻api,看到了这个dispatch文件,对里面的block比较感兴趣,所以查了下资料学习了一下。用处蛮大的。

    按照惯例先上头文件方法。

    创建block的方法
    dispatch_block_t
    dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
    创建block的方法,并可以指定优先级
    dispatch_block_t
    dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
            dispatch_qos_class_t qos_class, int relative_priority,
            dispatch_block_t block);
    创建,同步执行,并从指定的块和标志释放调度块。
    void
    dispatch_block_perform(dispatch_block_flags_t flags,
            DISPATCH_NOESCAPE dispatch_block_t block);
    同步等待,直到指定的调度块的执行完成,或者直到超过指定的超时时间。
    long
    dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
    
    当指定的调度块的执行完成时,安排通知块被提交给队列。
    void
    dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
            dispatch_block_t notification_block);
    异步取消指定的分派块
    void
    dispatch_block_cancel(dispatch_block_t block);
    测试给定的调度块是否被取消
    long
    dispatch_block_testcancel(dispatch_block_t block);
    

    上面就是block.h文件中的所有方法

    dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block)

    dispatch_block_flags_t 的枚举如下:

    DISPATCH_ENUM(dispatch_block_flags, unsigned long,
        DISPATCH_BLOCK_BARRIER
                DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x1,
        DISPATCH_BLOCK_DETACHED
                DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x2,
        DISPATCH_BLOCK_ASSIGN_CURRENT
                DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x4,
        DISPATCH_BLOCK_NO_QOS_CLASS
                DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x8,
        DISPATCH_BLOCK_INHERIT_QOS_CLASS
                DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x10,
        DISPATCH_BLOCK_ENFORCE_QOS_CLASS
                DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x20,
    );
    DISPATCH_BLOCK_BARRIER 保证代码块用于原子性,代码块的代码未执行结束前,下一次调用将进入一个FIFO的等待队列,等待本次代码块执行结束,使用较为安全,若不考虑线程安全可使用DISPATCH_BLOCK_DETACHED
    

    dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,

        dispatch_qos_class_t qos_class, int relative_priority,
        dispatch_block_t block);
    

    dispatch_qos_class_t 枚举如下

    QOS_CLASS_USER_INTERACTIVE:user interactive 等级表示任务需要被立即执行,用来在响应事件之后更新 UI,来提供好的用户体验。这个等级最好保持小规模。
    
    QOS_CLASS_USER_INITIATED:user initiated 等级表示任务由 UI 发起异步执行。适用场景是需要及时结果同时又可以继续交互的时候。
    
    QOS_CLASS_DEFAULT:default 默认优先级
    
    QOS_CLASS_UTILITY:utility 等级表示需要长时间运行的任务,伴有用户可见进度指示器。经常会用来做计算,I/O,网络,持续的数据填充等任务。这个任务节能。
    
    QOS_CLASS_BACKGROUND:background 等级表示用户不会察觉的任务,使用它来处理预加载,或者不需要用户交互和对时间不敏感的任务。
    
    QOS_CLASS_UNSPECIFIED:unspecified 未指明
    

    该看看具体的实现了

    dispatch_queue_t concurrentQuene = dispatch_queue_create("concurrentQuene", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_block_t block = dispatch_block_create(0, ^{
        NSLog(@"normal do some thing...");
    });
    dispatch_async(concurrentQuene, block);
    
    //
    dispatch_block_t qosBlock = dispatch_block_create_with_qos_class(0, QOS_CLASS_DEFAULT, 0, ^{
        NSLog(@"qos do some thing...");
    });
    dispatch_async(concurrentQuene, qosBlock);
    
    

    dispatch_block_perform(dispatch_block_flags_t flags,

        DISPATCH_NOESCAPE dispatch_block_t block);
    
    
        dispatch_block_t block = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
            NSLog(@"normal do some thing...");
        });
    //    dispatch_async(concurrentQuene, block);
        dispatch_block_perform(0, block);
    

    dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout)

    这是监听block执行是否结束的一种方法

    dispatch_queue_t concurrentQuene = dispatch_queue_create("concurrentQuene", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(concurrentQuene, ^{
        dispatch_queue_t allTasksQueue = dispatch_queue_create("allTasksQueue", DISPATCH_QUEUE_CONCURRENT);
    
        dispatch_block_t block = dispatch_block_create(0, ^{
            NSLog(@"开始执行");
            [NSThread sleepForTimeInterval:3];
            NSLog(@"结束执行");
        });
    
        dispatch_async(allTasksQueue, block);
        // 等待时长,10s 之后超时
        dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC));
        long resutl = dispatch_block_wait(block, timeout);
        if (resutl == 0) {
            NSLog(@"执行成功");
        } else {
            NSLog(@"执行超时");
        }
    });
    
    

    从这里可以看出 这个函数可以实现跟信号量差不多的功能吧。这个是同步的

    dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,

        dispatch_block_t notification_block);
    
    该函数接收三个参数,第一个参数是需要监视的 block,第二个参数是监听的 block 执行结束之后要提交执行的队列 queue,第三个参数是待加入到队列中的 block。 和  dispatch_block_wait 的不同之处在于:dispatch_block_notify 函数不会阻塞当前线程。
    这个是异步的
    
    NSLog(@"---- 开始设置任务 ----");
    dispatch_queue_t serialQueue =   dispatch_queue_create("com.xh.serialqueue",   DISPATCH_QUEUE_SERIAL);
    // 耗时任务
    dispatch_block_t taskBlock = dispatch_block_create(0, ^{
        NSLog(@"开始耗时任务");
        [NSThread sleepForTimeInterval:2.f];
        NSLog(@"完成耗时任务");
    });
    
    dispatch_async(serialQueue, taskBlock);
    // 更新 UI
    dispatch_block_t refreshUI = dispatch_block_create(0, ^{
        NSLog(@"更新 UI");
    });
    // 设置监听
    dispatch_block_notify(taskBlock, dispatch_get_main_queue(), refreshUI);
    NSLog(@"---- 完成设置任务 ----");
    
    

    dispatch_block_cancel(dispatch_block_t block)

    取消block执行

        dispatch_queue_t serialQueue = dispatch_queue_create("com.xh.serialqueue", DISPATCH_QUEUE_SERIAL);
    
        // 耗时任务
        dispatch_block_t firstTaskBlock = dispatch_block_create(0, ^{
            NSLog(@"开始第一个任务");
            [NSThread sleepForTimeInterval:1.5f];
            NSLog(@"结束第一个任务");
        });
    
        // 耗时任务
        dispatch_block_t secTaskBlock = dispatch_block_create(0, ^{
            NSLog(@"开始第二个任务");
            [NSThread sleepForTimeInterval:4.f];
            NSLog(@"结束第二个任务");
        });
    
        dispatch_async(serialQueue, firstTaskBlock);
        dispatch_async(serialQueue, secTaskBlock);
    
        // 等待 1s,让第一个任务开始运行
        [NSThread sleepForTimeInterval:1];
    
        dispatch_block_cancel(firstTaskBlock);
        NSLog(@"尝试过取消第一个任务");
    
        dispatch_block_cancel(secTaskBlock);
        NSLog(@"尝试过取消第二个任务");
    
    

    好了基本就这些了。

    想要找一群一起进步的人,请加入我

    image.png

    相关文章

      网友评论

          本文标题:『ios』GCD补习 dispatch block

          本文链接:https://www.haomeiwen.com/subject/ehbgtqtx.html