dispatch object.h

版本:iOS13.5

object.h

dispatch其他文件通道

索引

  • 增加调度对象object的引用计数
    dispatch_retain
  • 减少调度对象object的引用计数
    dispatch_release
  • 为调试对象object绑定一个参数指针context
    dispatch_set_context
  • 获取调试对象object绑定的参数指针
    dispatch_get_context
  • 为调度对象object设置终结函数
    dispatch_set_finalizer_f
  • 激活调度对象object
    dispatch_activate
  • 挂起调度对象object
    dispatch_suspend
  • 恢复已经挂起的调度对象object
    dispatch_resume
  • 为调度对象object设置qos_class
    dispatch_set_qos_class_floor
  • 同步等待对象object或超时
    dispatch_wait
  • 对象object全部执行后,将notification_block提交给队列queue再执行。
    dispatch_notify
  • 取消对象object
    dispatch_cancel
  • 测试对象object是否已被取消
    dispatch_testcancel

详解

  • 增加调度对象object的引用计数
void dispatch_retain(dispatch_object_t object);

引用计数大于0时不会被释放,只能在非ARC模式下使用。
必须和dispatch_release成对使用
object 调试对象 dispatch_queue_tdispatch_source_t都可以当做dispatch_object_t使用

  • 减少调度对象object的引用计数
void dispatch_release(dispatch_object_t object);

一旦引用计数为0后,系统会异步释放该对象

例:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_retain(queue);
    dispatch_release(queue);
  • 为调试对象object绑定一个参数指针context
void dispatch_set_context(dispatch_object_t object, void *_Nullable context);

context 为一个指针 void *类型 可以为NULL
该参数指针在dispatch_set_finalizer_f的finalizer调用时使用

  • 获取调试对象object绑定的参数指针
void *_Nullable dispatch_get_context(dispatch_object_t object);

例:

    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    int context = 10;
    dispatch_set_context(queue, &context);
    int *adress = dispatch_get_context(queue);
    NSLog(@"%d", *adress);
输出:
10
  • 为调度对象object设置终结函数
void dispatch_set_finalizer_f(dispatch_object_t object, 
              dispatch_function_t _Nullable finalizer);

终结函数是当object被释放时调用的函数
finalizer 终结函数的指针typedef void (*dispatch_function_t)(void *_Nullable);
此时finalizer所需的void *参数由dispatch_set_context方法来设置
可以在终结函数中释放与object关联的任何资源

例:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    int context = 10;
    dispatch_set_context(queue, &context);    
    NSLog(@"11");
    //在queue上添加了一个dispatch_after函数 此时queue不会释放 待after函数执行完后queue释放 然后触发终结函数finalizer
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"22");
    });
    dispatch_set_finalizer_f(queue, finalizer);

void finalizer(void *context) {
    NSLog(@"33");
}
输出:
11
22
33
  • 激活调度对象object
void dispatch_activate(dispatch_object_t object);

调度对象(例如queue和source)可以在非活动状态下创建。必须先激活这种状态的对象,然后才能调用与它们关联的任何block。
在活动对象上调用dispatch_activate是无效的
可以使用dispatch_set_target_queue更改非活动对象的目标队列。一旦最初不活动的对象被激活,就不再允许更改目标队列。

  • 挂起调度对象object
void dispatch_suspend(dispatch_object_t object);

挂起的对象object将不会调用与其关联的任何block。已经运行的block不会停止,并且在已经运行的block完成之后,才会挂起该对象object。
dispatch_suspend必须和dispatch_resume成对使用

  • 恢复已经挂起的调度对象object
void dispatch_resume(dispatch_object_t object);

对处于非活动状态且未挂起的dispatch_source_t对象调用dispatch_resume与调用dispatch_activate具有相同的效果。对于新代码,首选使用dispatch_activate

例:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    
    //在主队列中1秒后将queue挂起
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"开始挂起");
        dispatch_suspend(queue);
    });
    //因为queue已被挂起 虽然2秒已到 但block不会执行
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"2秒时的操作");
    });
    //在主队列中3秒后将queue恢复 因为2秒的操作时间已到,待queue一恢复 ,就会直接执行block
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"开始恢复");
        dispatch_resume(queue);
    });
输出:
开始挂起
开始恢复
2秒时的操作
  • 为调度对象object设置qos_class
void dispatch_set_qos_class_floor(dispatch_object_t object,
        dispatch_qos_class_t qos_class, int relative_priority);

object 调度对象 类型可为dispatch_queue_tdispatch_workloop_tdispatch_source_t
对象必须是非活跃的
qos_class 优先级从上住下依次变低

__QOS_ENUM(qos_class, unsigned int,
    //该线程执行的工作的QOS类会与用户交互。
    //此类工作相对于系统上的其他工作具有更高的优先级
    //这不是用于大型任务的高能效QOS类。
    //此QOS类的使用应限于与用户的关键交互,例如处理主事件循环上的事件,视图绘制,动画等
    QOS_CLASS_USER_INTERACTIVE = 0x21,
    //该线程执行的工作的QOS类由用户启动,并且用户可能正在等待结果
    QOS_CLASS_USER_INITIATED = 0x19,
    //默认
    QOS_CLASS_DEFAULT = 0x15,
    //该线程执行的工作的QOS类可能由用户启动也可能未启动,并且用户不太可能立即等待结果
    QOS_CLASS_UTILITY = 0x11,
    //指示该线程执行的工作的QOS类不是由用户启动的,并且用户可能不知道结果
    QOS_CLASS_BACKGROUND = 0x09,
    //未指定
    QOS_CLASS_UNSPECIFIED = 0x00,
);

relative_priority QOS类中的相对优先级。该值是与最大支持的调度程序优先级的负偏移量。传递大于0或小于QOS_MIN_RELATIVE_PRIORITY的值将导致返回NULL。
#define QOS_MIN_RELATIVE_PRIORITY (-15)

  • 同步等待对象object或超时
long dispatch_wait(void *object, dispatch_time_t timeout);

object 对象
若对象为dispatch_block_t则调用dispatch_block_wait
若对象为dispatch_group_t则调用dispatch_group_wait
若对象为dispatch_semaphore_t则调用dispatch_semaphore_wait
timeout 超时时间 可为DISPATCH_TIME_FOREVERDISPATCH_TIME_NOW或通过dispatch_time创建

例:
    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    dispatch_async(dispatch_queue_create("sem", DISPATCH_QUEUE_CONCURRENT), ^{
        NSLog(@"1");
        dispatch_wait(sem, DISPATCH_TIME_FOREVER);
        //两种写法效果一致
//        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
        NSLog(@"3");
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"2");
        dispatch_semaphore_signal(sem);
    });
输出:
17:19:01.336476+0800 DEMO[82832:8357215] 1
17:19:04.336522+0800 DEMO[82832:8356709] 2
17:19:04.336713+0800 DEMO[82832:8357215] 3
  • 对象object全部执行后,将notification_block提交给队列queue再执行。
void dispatch_notify(void *object, dispatch_object_t queue,
        dispatch_block_t notification_block);

object 对象
若对象为dispatch_block_t则调用dispatch_block_notify
若对象为dispatch_group_t则调用dispatch_group_notify
queue 要执行notification_block的队列

  • 取消对象object
void dispatch_cancel(void *object);

object 对象
若对象为dispatch_block_t则调用dispatch_block_cancel
若对象为dispatch_source_t则调用dispatch_source_cancel

  • 测试对象object是否已被取消
long dispatch_testcancel(void *object);

object 对象
若对象为dispatch_block_t则调用dispatch_block_testcancel
若对象为dispatch_source_t则调用dispatch_source_testcancel

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352