Swift中用DispatchQueue同步处理事件:实现去重与顺序执行
用串行DispatchQueue实现事件顺序处理+重复事件丢弃
嘿,这个需求其实很好解决——串行队列本身就能保证顺序处理,我们只需要加一层“重复事件拦截”的逻辑就行。下面是我常用的实现方案,逻辑清晰还能保证线程安全:
核心思路
- 用串行DispatchQueue管控所有事件的处理流程,确保事件按调用顺序执行,同时天然保证对去重容器的线程安全访问(不用额外加锁)。
- 维护一个
Set存储当前正在处理或等待处理的事件,每次新事件进来时先检查是否已在集合中,是则直接丢弃,否则加入队列和集合,处理完成后从集合移除。
具体代码实现
首先假设你的事件类型Event遵循Hashable(这样才能放进Set里,你需要根据实际业务实现相等性判断,比如基于事件ID):
// 示例事件类型,根据你的实际需求调整 struct Event: Hashable { let id: String // 用唯一ID判断事件是否重复 // 其他事件属性... } class EventProcessor { // 串行队列,专门处理事件 private let processingQueue = DispatchQueue(label: "com.yourapp.event.processing") // 存储待处理/正在处理的事件,保证线程安全的访问全在串行队列中进行 private var pendingEvents = Set<Event>() func process(ev: Event) { // 将事件处理任务加入串行队列 processingQueue.async { [weak self] in guard let self = self else { return } // 检查是否是重复事件:如果已经在处理或等待中,直接丢弃 guard !self.pendingEvents.contains(ev) else { print("重复事件已丢弃:\(ev.id)") return } // 将事件加入待处理集合 self.pendingEvents.insert(ev) // 处理完成后务必从集合移除,用defer保证即使处理逻辑抛出异常也会执行 defer { self.pendingEvents.remove(ev) } // 这里写你的实际事件处理逻辑 self.handleEvent(ev) } } private func handleEvent(_ ev: Event) { // 示例:模拟事件处理耗时 print("开始处理事件:\(ev.id)") Thread.sleep(forTimeInterval: 1) print("完成处理事件:\(ev.id)") } }
逻辑解释
- 线程安全:所有对
pendingEvents的操作都在串行队列中执行,避免了多线程竞争问题,不用额外加NSLock或os_unfair_lock。 - 重复拦截:不管是正在处理的事件,还是已经在队列里等待的事件,新的重复调用都会被直接丢弃。
- 顺序保证:串行队列会严格按照
process方法的调用顺序执行事件处理逻辑,不会出现乱序。
扩展说明
如果你的事件处理逻辑是异步的(比如包含网络请求、回调等),记得要在异步任务完成后再从pendingEvents中移除事件,而不是用defer(因为defer会在handleEvent返回时立即执行,而此时异步任务可能还没完成)。示例调整如下:
private func handleEvent(_ ev: Event) { // 模拟异步处理任务 URLSession.shared.dataTask(with: someUrl) { [weak self] data, response, error in // 异步任务完成后,回到串行队列更新集合 self?.processingQueue.async { self?.pendingEvents.remove(ev) } // 处理异步结果... }.resume() }
内容的提问来源于stack exchange,提问作者hacker_1989
相关产品推荐
相关产品推荐

