​ 学习学习dispatch_block,在向队列中添加任务时,可以直接在对应的函数中添加 block。但是如果想对任务进行操作,比如监听任务、取消任务,就需要获取对应的 block

1 创建Block

  • 第一种方式如下:

    1
    dispatch_block_t dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);

    ​ 在该函数中,flags 参数用来设置 block 的标记,block 参数用来设置具体的任务。flags 的类型为 dispatch_block_flags_t 的枚举,用于设置 block 的标记,定义如下:

    1
    2
    3
    4
    5
    6
    7
    8
    DISPATCH_ENUM(dispatch_block_flags, unsigned long,
    DISPATCH_BLOCK_BARRIER = 0x1,
    DISPATCH_BLOCK_DETACHED = 0x2,
    DISPATCH_BLOCK_ASSIGN_CURRENT = 0x4,
    DISPATCH_BLOCK_NO_QOS_CLASS = 0x8,
    DISPATCH_BLOCK_INHERIT_QOS_CLASS = 0x10,
    DISPATCH_BLOCK_ENFORCE_QOS_CLASS = 0x20,
    );
  • 第二种方式如下:

    1
    2
    3
    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);

    ​相比于 dispatch_block_create 函数,这种方式在创建 block 的同时可以指定了相应的优先级。dispatch_qos_class_tqos_class_t 的别名,定义如下:

    1
    2
    3
    4
    5
    #if __has_include(<sys/qos.h>)
    typedef qos_class_t dispatch_qos_class_t;
    #else
    typedef unsigned int dispatch_qos_class_t;
    #endif

    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 未指明

    egg:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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_USER_INTERACTIVE, 0, ^{
    NSLog(@"qos do some thing...");
    });
    dispatch_async(concurrentQuene, qosBlock);
    1
    2
    LQHelper[1528:112987] qos do some thing...
    LQHelper[1528:112985] normal do some thing...

2 监听 block 执行结束

​ 有时我们需要等待特定的 block 执行完成之后,再去执行其他任务。有两种方法可以获取到指定 block 执行结束的时机。

  • 第一种方式如下:

    1
    long dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);

    ​ 该函数会阻塞当前线程进行等待。传入需要设置的 block 和等待时间 timeout。timeout 参数表示函数在等待 block 执行完毕时,应该等待多久。如果执行 block 所需的时间小于 timeout,则返回 0,否则返回非 0 值。此参数也可以取常量 DISPATCH_TIME_FOREVER,这表示函数会一直等待 block 执行完,而不会超时。可以使用 dispatch_time 函数和 DISPATCH_TIME_NOW 常量来方便的设置具体的超时时间。

    ​ 如果 block 执行完成,dispatch_block_wait 就会立即返回。不能使用 dispatch_block_wait 来等待同一个 block 的多次执行全部结束;这种情况可以考虑使用 dispatch_group_wait 来解决。也不能在多个线程中,同时等待同一个 block 的结束。同一个 block 只能执行一次,被等待一次。

    注意:因为 dispatch_block_wait 会阻塞当前线程,所以不应该放在主线程中调用。

    egg:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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_ 大专栏  GCD学习 —— 三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(@"执行超时");
    }
    });
    1
    2
    3
    4
    5
    6
    7
    8
    执行结果:(把上面的sleepForTimeInterval:时间设置成3s)
    LQHelper[1582:121193] 开始执行
    LQHelper[1582:121194] 结束执行
    LQHelper[1582:121193] 执行成功
    执行结果:(把上面的sleepForTimeInterval:时间设置成12s)
    LQHelper[1582:121193] 开始执行
    LQHelper[1582:121194] 执行超时
    LQHelper[1582:121193] 结束执行
  • 第二种方法如下:

    1
    void 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 函数不会阻塞当前线程。

    egg:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    NSLog(@"---- 开始设置任务 ----");
    dispatch_queue_t serialQueue = dispatch_queue_create("com.itachi.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(@"---- 完成设置任务 ----");
    1
    2
    3
    4
    5
    6
    执行结果:
    LQHelper[1615:127135] ---- 开始设置任务 ----
    LQHelper[1615:127135] ---- 完成设置任务 ----
    LQHelper[1615:127227] 开始耗时任务
    LQHelper[1615:127227] 完成耗时任务
    LQHelper[1615:127135] 更新 UI

3 任务的取消

iOS8 后 GCD 支持对 dispatch block 的取消。方法如下:

1
void dispatch_block_cancel(dispatch_block_t block);

​ 这个函数用异步的方式取消指定的 block。取消操作使将来执行 dispatch block 立即返回,但是对已经在执行的 dispatch block 没有任何影响。当一个 block 被取消时,它会立即释放捕获的资源。如果要在一个 block 中对某些对象进行释放操作,在取消这个 block 的时候,需要确保内存不会泄漏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
dispatch_queue_t serialQueue = dispatch_queue_create("com.itachi.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:2.f];
NSLog(@"结束第二个任务");
}); dispatch_async(serialQueue, firstTaskBlock);
dispatch_async(serialQueue, secTaskBlock); // 等待1s,让第一个任务开始运行
[NSThread sleepForTimeInterval:1]; dispatch_block_cancel(firstTaskBlock);
NSLog(@"尝试过取消第一个任务"); dispatch_block_cancel(secTaskBlock);
NSLog(@"尝试过取消第二个任务");
1
2
3
4
5
执行结果:
LQHelper[1645:130881] 开始第一个任务
LQHelper[1645:130771] 尝试过取消第一个任务
LQHelper[1645:130771] 尝试过取消第二个任务
LQHelper[1645:130881] 结束第一个任务

可见 dispatch_block_cancel 对已经在执行的任务不起作用,只能取消尚未执行的任务。

转载自GCD 之任务操作

GCD学习 —— 三的更多相关文章

  1. HTTP学习三:HTTPS

    HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...

  2. TweenMax动画库学习(三)

    目录               TweenMax动画库学习(一)            TweenMax动画库学习(二)            TweenMax动画库学习(三)           ...

  3. 多线程-GCD学习笔记

    ********************************* 基本概念 *********************************** 1. Grand Central Dispatch ...

  4. Struts2框架学习(三) 数据处理

    Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:Value ...

  5. 4.机器学习——统计学习三要素与最大似然估计、最大后验概率估计及L1、L2正则化

    1.前言 之前我一直对于“最大似然估计”犯迷糊,今天在看了陶轻松.忆臻.nebulaf91等人的博客以及李航老师的<统计学习方法>后,豁然开朗,于是在此记下一些心得体会. “最大似然估计” ...

  6. DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件

    DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件   本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...

  7. [ZZ] 深度学习三巨头之一来清华演讲了,你只需要知道这7点

    深度学习三巨头之一来清华演讲了,你只需要知道这7点 http://wemedia.ifeng.com/10939074/wemedia.shtml Yann LeCun还提到了一项FAIR开发的,用于 ...

  8. SVG 学习<三>渐变

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  9. Android JNI学习(三)——Java与Native相互调用

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

随机推荐

  1. BBS登录功能

    BBS登录功能 一.后端实现 1.实现验证码 from PIL import Image, ImageDraw, ImageFont import random from io import Byte ...

  2. macbook 安装laravel5.4

    1.安装composer php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');&q ...

  3. dubbo的本地存根

    在消费者创建存根类 修改消费者XML 也可以修改消费者注解

  4. JS控制 input 输入字符限制全搜集

    ENTER键可以让光标移到下一个输入框 <input onkeydown="if(event.keyCode==13)event.keyCode=9" > 只能是中文 ...

  5. Python 爬虫 爬取图片入门

    爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 用户看到的网页实质是由 HTML 代码构成的,爬 ...

  6. macOS更新失败解决

    下载离线更新包解决. https://support.apple.com/downloads/combo

  7. spring自定义aop

    package com.dhht.config.articleAdvice; import com.dhht.util.UUIDUtil;import lombok.extern.slf4j.Slf4 ...

  8. [LC] 151. Reverse Words in a String

    Given an input string, reverse the string word by word. Example 1: Input: "the sky is blue" ...

  9. K - Wand(组合数+错排公式)

    N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, ...

  10. day12-模块导入

    # 一.import import demo # in demo.py -- 导入demo模块,执行里面的print语句. print(demo.money) # 8000000 -- 打印demo的 ...