GCD dispatch source

本文深入探讨了dispatchsource的工作原理及其在GCD中的应用。从dispatchsource的基础概念出发,介绍了各种类型如定时器、信号、描述符等,并详细讲解了如何创建和配置dispatchsource,以及如何通过dispatchsource实现事件监听和处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    根据苹果的官方文档,dispatch source是基础数据类型,协调特定底层系统事件的处理,用于监听一些特定类型的事件对象,接收到事件发生时,自动将一个block压入一个线程。配置一个dispatch source时,需要指定要监测的事件、dispatch queue、以及处理事件的代码(block或函数),当事件发生时,dispatch source会提交block或函数到指定的queue去执行。如果不显示取消这个source,那么这个事件发生一次,block就会被提交执行一次。为了防止事件积压到dispatch queue,dispatch source实现了事件合并机制。如果新事件在上一个事件处理器出列并执行之前到达,dispatch source会将新旧事件的数据合并。根据事件类型的不同,合并操作可能会替换旧事件,或者更新旧事件的信息。

1.GCD所支持的dispatch source类型有:
  • Timer dispatch sources generate periodic notifications. 定期产生的(DISPATCH_SOURCE_TYPE_TIMER

  • Signal dispatch sources notify you when a UNIX signal arrives. 接受到UNIX信号时产生的 (DISPATCH_SOURCE_TYPE_SIGNAL)

  • Descriptor sources notify you of various file- and socket-based operations, such as: 为提示多种文件或socket操作产生的,比如:

    • When data is available for reading 文件可读 (DISPATCH_SOURCE_TYPE_READ

    • When it is possible to write data  文件可写 (DISPATCH_SOURCE_TYPE_WRITE)

    • When files are deleted, moved, or renamed in the file system  文件在系统中被删除,移动或重命名 (DISPATCH_SOURCE_TYPE_VNODE)

    • When file meta information changes  文件元信息被改变

  • Process dispatch sources notify you of process-related events, such as: 为提示有关进程的事件而产生的(DISPATCH_SOURCE_TYPE_PROC),比如:

    • When a process exits  退出一个进程

    • When a process issues a fork or exec type of call  进程发起一个fork或exec类型调用

    • When a signal is delivered to the process  信号递送至进程

  • Mach port dispatch sources notify you of Mach-related events. 为提示有关Mach相关事件而产生的 (DISPATCH_SOURCE_TYPE_MACH_SEND   DISPATCH_SOURCE_TYPE_MACH_RECV

  • Custom dispatch sources are ones you define and trigger yourself. 用户自定义且自己触发的 (DISPATCH_SOURCE_TYPE_DATA_ADD   DISPATCH_SOURCE_TYPE_DATA_OR

2.创建dispatch source
    创建dispatch source必须同时创建source of the events and the dispatch source itself,我的理解是事件信息和source,事件信息就是你要响应这个事件,所需要掌握的一些信息。然后:
  1. dispatch_source_create创建dispatch source,
    dispatch_source_t dispatch_source_create(
       dispatch_source_type_t type,
       uintptr_t handle,
       unsigned long mask,
       dispatch_queue_t queue);
    第一个参数代表:dispatch source类型,最后一个是block会进入的queue,用来执行事件处理器和取消处理器,第二三个参数在会根据source类型设置
  2. 配置dispatch source:
    • dispatch_source_set_event_handler设置dispatch source的事件处理器,就是响应了,干什么。
    • 如果是计时器,用dispatch_source_set_timer函数设置定时器信息
      void dispatch_source_set_timer(
         dispatch_source_t source,
         dispatch_time_t start,//开始时间
         uint64_t interval,//时间间隔,纳秒级别的
         uint64_t leeway);//系统可延迟的时间,纳秒级别的,就是精度
  3. 可以选择添加一个取消source后的事件处理器,也可以忽略,取消处理器在dispatch soruce释放之前执行清理工作,使用描述符或Mach port的dispatch source必须设置取消处理器
  4. source默认是挂起的,需要恢复,用dispatch_resume

3.修改queue
用 dispatch_set_target_queue 函数在任何时候异步修改目标queue,主要用于修改queue的优先级,系统会尽快完成这个异步操作。未进入queue的事件处理器会在新的queue执行,已进入的在旧的执行。

4.DISPATCH_SOURCE_TYPE_TIMER 使用

假如需要一个一分钟报时一次的时钟dispatch_time 是之于计算机时间,是相对时间,dispatch_walltime 是之于挂钟,是绝对时间,码如下:

    /* step 1 */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,//类型:定时器
                                   0, 0,
                                   queue);//block会被压入queue执行
    /* step 2 */
    dispatch_source_set_timer(timer,//dispatch source
                              dispatch_time(DISPATCH_TIME_NOW, 0* NSEC_PER_SEC),//现在开始
                              1* NSEC_PER_SEC,//间隔 1s
                              0);//精度0
    /* step 3 */
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"!");//整秒报时时的操作
    });
    /* step 4 */
    dispatch_resume(timer);//恢复source

5.DISPATCH_SOURCE_TYPE_DATA_ADD/ DISPATCH_SOURCE_TYPE_DATA_OR

    NSArray *name = @[@"a",@"b",@"c",@"d",@"e"];
    dispatch_source_t  source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_event_handler(source, ^{
        NSLog(@"%lu 人已交卷",dispatch_source_get_data(source));
    });
    dispatch_resume(source);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_apply(5, queue, ^(size_t index) {
        NSLog(@"收到 %@ 试卷",name[index]);
        dispatch_source_merge_data(source, 1);
    });
这个是用户自己完成某些操作后,触发事件,然后响应事件。 dispatch_source_merge_data发出信号,然后执行事件处理器中的代码。 dispatch_source_merge_data 有两个参数,第一个是source,第二个是一个unsigned long属性, DISPATCH_SOURCE_TYPE_DATA_ADD 是将每一个异步线程中发送的这些数据加起来,_OR是将这些数据逻辑与运算。

6. dispatch_source_cancel

dispatch_source_cancel异步取消一个source,取消之后不会再发送新的事件,无法撤销,之后会执行取消处理器代码。取消时正在执行的代码不会停止。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值