GCD 中的 Block

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011374318/article/details/88142069

GCD 中的 Block

在 GCD 中,可以使用 block.h 中的函数实现 block 的创建、执行和取消。

dispatch_block_t dispatch_block_create(dispatch_block_flags_t flags, 
										dispatch_block_t block);

该方法会根据提供的 block 以及 flags 标识,在堆上创建一个新的 block ,这个新的 block 可能会被 dispatch_async() 等相关方法添加到队列中去,也可能会被直接执行。

当 block 被提交到队列中时,其相关联的优先级不仅仅同其指定的 flags 值有关,也同其要加入的队列有关。

dispatch_block_flags_tunsigned long 类型的枚举值,相关值如下:

名称 具体值 说明
DISPATCH_BLOCK_BARRIER 0x1 表示 block 被提交到并行队列中时,应作为分隔 block
DISPATCH_BLOCK_DETACHED 0x2 表示 block 被执行时,并不使用当前执行上下文中的参数,如果是直接执行,那么在执行体中,其将移除来自执行线程的属性参数;
如果是提交到了队列中,那么其将使用队列的参数及其本身的参数。
DISPATCH_BLOCK_ASSIGN_CURRENT 0x4 表示在创建 block 时,当前上下文中的属性应传递给该 block ,若该 block 直接执行,那么在执行过程中,这些属性应当应用于执行线程中;
如果是提交到队列中,那么提交时刻的属性状态将替代 block 提交时的默认属性状态。
DISPATCH_BLOCK_NO_QOS_CLASS 0x8 表示并不为 block 指定相关属性,如果是直接执行,那么使用执行线程的优先级属性;
如果是提交到队列,那么使用提交时的优先级属性。
DISPATCH_BLOCK_INHERIT_QOS_CLASS 0x10 表示 block 被提交到队列中时,优先使用队列相关的优先级属性,除非队列并没有关联优先级。并且,该值是使用 dispatch_async() 函数添加 block 到队列中时的默认值。
另外,如果同时传递了 DISPATCH_BLOCK_ENFORCE_QOS_CLASS 值,那么 DISPATCH_BLOCK_INHERIT_QOS_CLASS 将被忽略。
DISPATCH_BLOCK_ENFORCE_QOS_CLASS 0x20 表示 block 被提交到队列中时,优先使用 block 相关联的优先级属性,只要其不会导致优先级的降低。并且该值是使用 dispatch_sync() 函数添加 block 到队列中或直接执行 block 时的默认值。

这些标识表示需要使用怎样的优先级,但是实际上 iOS 系统中有专门的类型来表示优先级的不同。

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

从该定义可知,在 qos.h 文件中存在 qos_class_t 的定义。

在线程的执行过程中,涉及到时延、CPU 、输入、输出以及网络访问等资源的使用,那么便需要一个变量来描述不同线程对这些资源的访问顺序。这个对线程资源访问先后的描述,也可以称作线程的优先级,但是这个优先级不能超过整个进程的优先级。

qos_class_tunsigned int 类型的枚举值,其相关值如下:

名称 具体值 说明
QOS_CLASS_USER_INTERACTIVE 0x21 表示当前线程中的任务是与用户交互的,其权限高于系统中的其他任务,几乎拥有所有 CPU 及输入输出带宽资源,耗费电量较大,所以除了诸如手势事件、绘图、动画等与用户交互的任务,不宜使用该权限。
QOS_CLASS_USER_INITIATED 0x19 表示当前线程中的任务是由用户触发的,并且用户正在等待任务处理结果。其权限低于用户交互任务权限,但是高于其他任务,并且不是高效能的,所以只适用于短期可得到执行结果的任务。
QOS_CLASS_DEFAULT 0x15 表示系统默认的线程优先级类别,如 pthread_create() 创建的线程就默认使用该类别。其权限低于用户交互任务以及用户处罚任务的权限,但是高于公共任务及后台任务。
QOS_CLASS_UTILITY 0x11 表示当前线程中的任务是普通任务,用户并不需要立即知道其执行结果,也不在意其执行过程,但其权限比系统维护的低级别任务较高,且执行过程是高效能的。
QOS_CLASS_BACKGROUND 0x09 表示线程中的任务并不是用户触发的,而且用户可能也不需要知道执行结果,其权限比其他任务权限要低。
QOS_CLASS_UNSPECIFIED 0x00 表示缺少或已经移除了优先级类别信息,作为 API 的返回值,可能表示线程属性配置同旧 API 不兼容或是同 QOS 类别系统相冲突。

在同一个优先级类别中,还有一个相对优先级的值,该值小于 0 并且大于 -15 ,包括 0 和 -15 ,这个相对值只在当前进程及相同类别中有意义。

#define QOS_MIN_RELATIVE_PRIORITY (-15)

通过下面两个方法可以获取当前线程以及主线程的优先级类别。

qos_class_t qos_class_self(void);

qos_class_t qos_class_main(void);

理解上面的枚举值,便可以理解下面这个 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);

在创建 block 时,为其指定优先级权限类别以及相对权限。那么,block 具体执行时的权限则由 flagsqos_class 共同决定。

void dispatch_block_perform(dispatch_block_flags_t flags,
					DISPATCH_NOESCAPE dispatch_block_t block);

根据指定的标识以及 block 创建一个新的 block 执行并释放,如同下面的代码:

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

应注意这个函数的执行是同步的。

long dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);

同步等待指定的 block 执行完毕,或者超时。

void dispatch_block_notify(dispatch_block_t block, 
							dispatch_queue_t queue,
							dispatch_block_t notification_block);

监听指定的 block ,当其执行完毕后,执行指定的 block 。

void dispatch_block_cancel(dispatch_block_t block);

取消指定 block 的执行,但是对于已经执行的 block 无效。

猜你喜欢

转载自blog.csdn.net/u011374318/article/details/88142069