dispatch_block_t

dispatch_block_t

typedef void (^dispatch_block_t)(void);

注意:
声明的block是分配在stack上的

//下面写法是错误的
dispatch_block_t block;
if (x) {
block = ^{ printf("true\n"); };
} else {
block = ^{ printf("false\n"); };
}
block();

block是在栈上的,当{}退出时,block就无效了

dispatch_block_create_with_qos_class

在堆上创建新的dispatch block,指定其执行block,分配指定的QoS类和相对优先级

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);
//flags 设置block的标记 必须为有效的位标记,否则返回NULL
//qos_class QoS类, 这个值传QOS_CLASS_UNSPECIFIED 相当于DISPATCH_BLOCK_NO_QOS_CLASSflag
//指定qos类的相对优先级 越大优先级越高 为负值 不能赋值给其大于0 小于QOS_MIN_RELATIVE_PRIORITY的值 否则会返回NULL

提供的参数block会被copy到堆上,被新创建的dispatch block持有

这个block可以dispatch_async到queue中执行或者直接执行
block可以用这两种方式多次执行,但是只有第一次执行的block可以被dispatch_block_wait等待或者dispatch_block_notify.监听

直接执行时,如果分配的QoS类比调用的线程的QoS类优先级高,则使用分配的QoS类执行
如果dispatch block到queue中执行,则执行它的QoS类取决于分配给bloc的QoS,queue的QoS或者flags共同决定
如果block被直接提交到串行队列执行,则QoS类无效,系统会尽力覆盖QoS使先执行的block的QoS类等级更高,优先执行

//flag的类型
DISPATCH_ENUM(dispatch_block_flags, unsigned long,
    DISPATCH_BLOCK_BARRIER = 0x1,
    /**
    当在一个DISPATCH_QUEUE_CONCURRENT的queue中执行dispatch block时
    表明这个block是barrier,即使不使用dispatch_barrier_async函数也可以在起到栅栏作用
    在直接执行dispatch block时,这个flags无效
    */
    DISPATCH_BLOCK_DETACHED = 0x2,
    /**
    将dispatch block与当前执行的context(上下文)分离
    */
    DISPATCH_BLOCK_ASSIGN_CURRENT = 0x4,
    /**
    指定dispatch block使用当前执行的context
    */
    DISPATCH_BLOCK_NO_QOS_CLASS = 0x8,
    /**
    表示不为block分配QoS类
    直接执行block,则使用调用线程的QoS
    如果给该block分配了特定QoS类,则该flag设置无效,忽略
    */
    DISPATCH_BLOCK_INHERIT_QOS_CLASS = 0x10,
    /**
        Queue的QoS类优先于block的QoS类,只有当队列没有QoS时才会使用block的QoS
        在直接调用block时,该flags值无效
        将block提交到queue中异步执行时,该值为默认值
        当设置了DISPATCH_BLOCK_ENFORCE_QOS_CLASS时,该default flag被忽略
    */
    DISPATCH_BLOCK_ENFORCE_QOS_CLASS = 0x20,
    /**
        表示当block的QoS类优先级高于Queue的QoS类时,优先选择block的QoS类
        当直接执行block或者将block提交到Queue中进行同步执行时,此为默认值
    */
);

DISPATCH_BLOCK_BARRIER即在自己创建的并行队列中 做栅栏block

DISPATCH_BLOCK_DETACHEDDISPATCH_BLOCK_ASSIGN_CURRENTDISPATCH_BLOCK_NO_QOS_CLASS用于dispatch_block_create函数,而在dispatch_block_create_with_qos_class中指定了QoS类,该flag就失效了

Quality of Service Classes (QoS).

__QOS_ENUM(qos_class, unsigned int,
    QOS_CLASS_USER_INTERACTIVE = 0x21,
        /**
          表示任务需要被立即执行 响应事件更新UI 用来处理主事件循环、视图绘制、动画等
        */
    QOS_CLASS_USER_INITIATED = 0x19,
        /**
          表示任务由UI发起异步任务。等待结果
        */
    QOS_CLASS_DEFAULT = 0x15,
        /**
          默认优先级
        */
    QOS_CLASS_UTILITY = 0x11,
        /**
          表示需要长时间运行任务,伴有进度指示器;用来做计算、I/O,网络,持续数据填充等
        */
    QOS_CLASS_BACKGROUND = 0x09,
        /**
          表示用户不需要察觉的任务,用来预处理加载
        */
    QOS_CLASS_UNSPECIFIED = 0x00,
        /**
          未指明
        */
);

dispatch_block_create

dispatch_block_t dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
//flags 设置block的标记 必须为有效的位标记,否则返回NULL 与上面的flag相同
//block设置具体任务 block将会copy到新的dispatch block中

当返回的dispath block被提交到queue中执行时,block与当前提交时的QoS类相关联,除非有以下flags在创建block时指定了QoS类(或者不指定QoS类):
DISPATCH_BLOCK_ASSIGN_CURRENT
DISPATCH_BLOCK_NO_QOS_CLASS
DISPATCH_BLOCK_DETACHED

当dispatch block在queue中执行时,则执行它的QoS类取决于分配给bloc的QoS,queue的QoS或者flags共同决定:
DISPATCH_BLOCK_INHERIT_QOS_CLASS(异步执行默认值)
DISPATCH_BLOCK_INHERIT_QOS_CLASS(同步执行默认值)

dispatch_block_perform

void dispatch_block_perform(dispatch_block_flags_t flags, dispatch_block_t block);

通过指定flag和block,同步执行该block,并且release生成的dispatchBlock

这个函数相当于下面这段代码:
并且与下面这段代码相比,不需要将block copy到堆上开辟新的内存,在内部更高效的实现

dispatch_block_t b = dispatch_block_create(flags, block);
b();
Block_release(b);

dispatch_block_wait

同步等待dispatch Block执行完成 或者 超时
会阻塞当前线程

long dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
//block: 应该为dispatch_block_create 或者dispatch_block_create_with_qos_class 创建的block
//超时时间:  
//返回值: 如果执行block时间小于超时时间返回0,否则返回非0

同一个block只会被等待一次,执行多次,也只能同时被一个等待

  1. dispatch_block_wait 只会监听第一个block执行情况,如果已经执行过一次了,这个函数就会立即返回
  2. 请使用dispatch_group_wait监听统一block的多次执行
  3. 不能在多线程中同时执行该函数等待同一个block返回,因为block只能等待一次
  4. 如果该函数返回超时,则这次等待不算,即还可以再次等待block完成,否则只能等待一次
  5. 提交到queue执行block即使立即用dispatch_block_cancel使其不执行,这也算执行过一次了

dispatch_block_notify

监听block执行完成,将要执行的block放入queue指定queue中执行

void dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue, dispatch_block_t notification_block);
//block: 监听的block  应该为dispatch_block_create 或者dispatch_block_create_with_qos_class 创建的block
//queue
//notification_block: 当监听的block执行完成 执行的block
  1. 当监听的block已经完成 该监听block会立即执行
  2. 无法监听相同block的多次执行的,请使用dispatch_group_notify
  3. block可以执行一次 监听多次
  4. 如果多个监听统一block执行,不能预期监听的block执行顺序
  5. 提交到queue执行block即使立即用dispatch_block_cancel使其不执行,这也算执行过一次了

dispatch_block_cancel

异步取消指定dispatch block

void dispatch_block_cancel(dispatch_block_t block);
//block: 应该使用dispatch_block_create 或者dispatch_block_create_with_qos_class 创建的block

对于所有未执行的block去 立即返回并不执行,但是对于那些已经在执行的 则没有影响

注意: 确保可能被取消的block不持有任何需要执行block才会释放的资源,例如malloc内存,否则由于永远不执行block块导致内存泄漏

已经被cancel的block无法再执行

dispatch_block_testcancel

测试是否这个block已经被取消

long dispatch_block_testcancel(dispatch_block_t block);
//返回: 被取消的话返回非0,否则返回0