Swift串行DispatchQueue未串行执行问题求助
问题描述
我的代码中sendRequest函数会被多次调用,该函数负责向服务器发送请求,服务器会逐个处理请求并返回多个响应。我希望handleResponse函数在串行队列中处理这些响应,同一时间仅执行一次,但日志显示handleResponse还没执行完就被多次调用了。简化后的代码如下:
func sendRequest() { // 被多次调用 applicationNetworkManager().sendQuery( ... successHandler: { response in let workItem = DispatchWorkItem { self!.handleResponse(response: response) } let serialQueue = DispatchQueue(label: "serialQueue", qos: .background) serialQueue.async(execute: workItem) } ) } func handleResponse(response: Response) { Logger.d("start handleResponse") // 执行一些操作并将响应数据写入本地存储 DispatchQueue.main.async { // 更新UI } Logger.d("end handleResponse") }
请问如何让回调按串行方式工作?
解决方案
问题核心是你每次进入successHandler时都会创建新的串行队列,这些队列相互独立,各自的任务会并行执行,根本起不到串行控制的作用。
只需要把串行队列改为类的成员属性,确保所有回调任务都提交到同一个串行队列即可:
// 在类内部定义全局的串行队列,而非在回调里临时创建 private let serialResponseQueue = DispatchQueue(label: "serialResponseQueue", qos: .background) func sendRequest() { // 被多次调用 applicationNetworkManager().sendQuery( ... successHandler: { [weak self] response in guard let self = self else { return } self.serialResponseQueue.async { self.handleResponse(response: response) } } ) } func handleResponse(response: Response) { Logger.d("start handleResponse") // 执行一些操作并将响应数据写入本地存储 DispatchQueue.main.async { // 更新UI } Logger.d("end handleResponse") }
额外说明:
- 用
[weak self]配合guard let解包,比直接使用self!更安全,避免循环引用风险 - 同一个串行队列会严格按任务添加顺序执行,前一个任务执行完毕后才会启动下一个,确保
handleResponse同一时间仅执行一次
内容的提问来源于stack exchange,提问作者Takrem
相关产品推荐
相关产品推荐

