1-18.【GCD】DispatchSource 是什么?解决了什么问题?

3 阅读2分钟

DispatchSource 是 GCD(Grand Central Dispatch)提供的一种 高性能事件源机制,用于监听系统或自定义事件,并在事件发生时异步响应。它本质上是 事件驱动的观察者模式 + GCD 调度

下面系统拆开讲。


1️⃣ DispatchSource 的本质

DispatchSource 是一个“事件源对象”,把异步事件和 GCD 队列绑定,当事件发生时会自动把处理 block 派发到指定队列执行。

  • 类似一个 异步回调注册器
  • 事件类型非常丰富(文件 I/O、信号、定时器、进程状态等)
  • 高效、无需轮询

2️⃣ 解决了什么问题

在传统模型下:

  • 监听文件描述符变化(如 socket) → select / poll / kqueue
  • 定时器 → NSTimer(可能阻塞 RunLoop)
  • 信号处理 → 手动注册信号回调

问题:

  1. 需要自己管理线程或 RunLoop
  2. 回调难以与队列调度结合
  3. 并发处理复杂,性能受限

DispatchSource 解决:

  • 事件驱动 + GCD 调度
  • 自动在指定队列异步执行回调
  • 线程安全 + 高性能
  • 不需要手动创建线程或轮询

3️⃣ DispatchSource 的主要类型

常用类型包括:

类型监听事件用途示例
DISPATCH_SOURCE_TYPE_TIMER定时高精度定时器、循环任务
DISPATCH_SOURCE_TYPE_READ文件描述符可读Socket 数据到达、管道可读
DISPATCH_SOURCE_TYPE_WRITE文件描述符可写Socket 可写、文件写入可用
DISPATCH_SOURCE_TYPE_SIGNALPOSIX 信号处理信号事件
DISPATCH_SOURCE_TYPE_PROC进程状态子进程退出、信号
DISPATCH_SOURCE_TYPE_MACH_RECV/PORTMach 消息Mach IPC 通信

4️⃣ DispatchSource 的使用模式

典型步骤:

let source = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
source.schedule(deadline: .now(), repeating: 1.0)
source.setEventHandler {
    print("Timer fired")
}
source.resume()  // 必须 resume 才能启动

特点:

  • setEventHandler → 注册回调
  • resume → 启动事件源
  • 回调在指定队列执行 → 可以和其他 GCD 队列任务无缝并发
  • 无需手动线程、轮询或 RunLoop

文件描述符示例

let fd: Int32 = open("file.txt", O_EVTONLY)
let source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fd, eventMask: .write, queue: DispatchQueue.global())
source.setEventHandler {
    print("File changed")
}
source.resume()
  • 当文件可写时触发回调
  • 异步执行在指定队列
  • 无需轮询文件状态

5️⃣ DispatchSource 的优势

  1. 异步、非阻塞

    • 回调在 GCD 队列中执行,线程安全
  2. 高性能

    • 底层用内核机制(kqueue / epoll / Mach port)
  3. 统一模型

    • 定时器、I/O、信号、进程状态都用同一 API
  4. 易于组合

    • 可以和串行队列 / 并发队列 / barrier 等 GCD 机制一起使用

6️⃣ 总结一句话

DispatchSource 是 GCD 提供的事件源机制,用于异步、线程安全、高性能地监听系统或自定义事件,解决传统轮询、线程管理复杂和回调调度难的问题。