DispatchSource 是 GCD(Grand Central Dispatch)提供的一种 高性能事件源机制,用于监听系统或自定义事件,并在事件发生时异步响应。它本质上是 事件驱动的观察者模式 + GCD 调度。
下面系统拆开讲。
1️⃣ DispatchSource 的本质
DispatchSource 是一个“事件源对象”,把异步事件和 GCD 队列绑定,当事件发生时会自动把处理 block 派发到指定队列执行。
- 类似一个 异步回调注册器
- 事件类型非常丰富(文件 I/O、信号、定时器、进程状态等)
- 高效、无需轮询
2️⃣ 解决了什么问题
在传统模型下:
- 监听文件描述符变化(如 socket) →
select/poll/kqueue - 定时器 → NSTimer(可能阻塞 RunLoop)
- 信号处理 → 手动注册信号回调
问题:
- 需要自己管理线程或 RunLoop
- 回调难以与队列调度结合
- 并发处理复杂,性能受限
DispatchSource 解决:
- 事件驱动 + GCD 调度
- 自动在指定队列异步执行回调
- 线程安全 + 高性能
- 不需要手动创建线程或轮询
3️⃣ DispatchSource 的主要类型
常用类型包括:
| 类型 | 监听事件 | 用途示例 |
|---|---|---|
DISPATCH_SOURCE_TYPE_TIMER | 定时 | 高精度定时器、循环任务 |
DISPATCH_SOURCE_TYPE_READ | 文件描述符可读 | Socket 数据到达、管道可读 |
DISPATCH_SOURCE_TYPE_WRITE | 文件描述符可写 | Socket 可写、文件写入可用 |
DISPATCH_SOURCE_TYPE_SIGNAL | POSIX 信号 | 处理信号事件 |
DISPATCH_SOURCE_TYPE_PROC | 进程状态 | 子进程退出、信号 |
DISPATCH_SOURCE_TYPE_MACH_RECV/PORT | Mach 消息 | 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 的优势
-
异步、非阻塞
- 回调在 GCD 队列中执行,线程安全
-
高性能
- 底层用内核机制(kqueue / epoll / Mach port)
-
统一模型
- 定时器、I/O、信号、进程状态都用同一 API
-
易于组合
- 可以和串行队列 / 并发队列 / barrier 等 GCD 机制一起使用
6️⃣ 总结一句话
DispatchSource 是 GCD 提供的事件源机制,用于异步、线程安全、高性能地监听系统或自定义事件,解决传统轮询、线程管理复杂和回调调度难的问题。