You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中用DispatchQueue同步处理事件:实现去重与顺序执行

用串行DispatchQueue实现事件顺序处理+重复事件丢弃

嘿,这个需求其实很好解决——串行队列本身就能保证顺序处理,我们只需要加一层“重复事件拦截”的逻辑就行。下面是我常用的实现方案,逻辑清晰还能保证线程安全:

核心思路

  1. 用串行DispatchQueue管控所有事件的处理流程,确保事件按调用顺序执行,同时天然保证对去重容器的线程安全访问(不用额外加锁)。
  2. 维护一个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:51:59