【问题标题】:Swift DispatchSemaphore is freezing the applicationSwift DispatchSemaphore 正在冻结应用程序
【发布时间】:2023-03-07 09:47:01
【问题描述】:

我尝试使用 DispatchSemaphore 在循环中运行 API 服务,它冻结了应用程序, 我的要求是我已经调用 API 来获取详细信息列表每个详细信息我有不同的请求,我需要在循环中调用 API,每个 API 都依赖于先前 API 的响应,因此我使用了 DispatchSemaphore 等待和信号方法,但它正在释放应用程序

示例代码:

func DownloadInformation(urlString: String, device: String, indexValue: Int, completion: @escaping (_ requestIndex: Int?) -> (Void)) {
        ApiService.sharedInstance.DownloadHealthInsightDetails(ID: self.equipmentAnalaysisArr[indexValue].id) { [self] (serverResponse, error, cardID) -> (Void) in
            if(serverResponse != nil && error == nil) {
                let insightCycleList = serverResponse as? NSDictionary
                if (insightCycleList?["error"]) == nil {
                                                            
                    if let cycle = insightCycleList?["cycles"] as? [AnyObject], cycle.count != 0 {
                        let dispatchGroup = DispatchGroup()
                        let dispatchQueue = DispatchQueue(label: "taskQueue")
                        let dispatchSemaphore = DispatchSemaphore(value: 0)
                            for i in 0..<cycle.count {
                                if i < 5 {
                                    dispatchGroup.enter()
                                    let element = cycle[i]
                                                                            
                                        self.DownloadCycleData(urlString: blob_url , cycleDownloadCompletion: {_ in
                                            completion(indexValue)
                                            dispatchSemaphore.signal()
                                            dispatchGroup.leave()
                                        })
                                    dispatchSemaphore.wait()
                                }
                            }
                            
                        dispatchGroup.notify(queue: DispatchQueue.main) {
                                print("done")
                            }
//                        }
                    } else {
                        self.ShowMessage(index: indexValue, message: self.message)
                    }
                }else {
                    self.ShowMessage(index: indexValue, message: self.message)
                }
            }
        }
    }

谁能给我建议来解决这个问题?

谢谢。

【问题讨论】:

  • 作为对潜在回答者的礼貌,请发布您的真实代码(它是Void而不是void)并缩进代码正确。
  • 贴出我的原码请查收
  • 阻塞执行是信号量的唯一工作,这并不奇怪。有点令人惊讶的是,您使用信号量来序列化所有对DownloadCycleData 的调用。你为什么这样做?与 IO 相关的任务从能够并发运行中受益匪浅。
  • 每个响应都依赖于前一个响应,因此我使用信号量
  • 或者我们可以通过其他方式实现这一目标吗?

标签: ios swift iphone xcode


【解决方案1】:

您没有使用 DispatchQueue(label: "taskQueue")。 但也许你应该考虑在这种情况下使用一些状态机。

if let cycle = insightCycleList?["cycles"] as? [AnyObject], cycle.count != 0 {
    let dispatchQueue = DispatchQueue(label: "taskQueue")
    let semaphore = DispatchSemaphore(value: 0)
    dispatchQueue.async {
        for i in 0..<cycle.count {
            if i < 5 {
                let cycleSemaphore = DispatchSemaphore(value: 0)
                let element = cycle[i]
                self.DownloadCycleData(urlString: blob_url , cycleDownloadCompletion: {_ in
                    completion(indexValue)
                    cycleSemaphore.signal()
                })
                cycleSemaphore.wait()
            }
        }
        semaphore.signal()
    }
    semaphore.wait()
}

【讨论】:

  • 谢谢你的建议,我会像你提到的那样添加信号量信号看看
  • 但问题是我们已经在运行后台任务 (ApiService.sharedInstance.DownloadHealthInsightDetails) 如果我们在 dispatchQueue 中执行此操作会再次起作用吗?
  • 那么你就不需要 dispatchQueue
  • 这是不工作的cycleSemaphore.wait() 阻塞整个进程
  • 你提到的上面的代码你使用的是两个不同的信号量吗?
猜你喜欢
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
相关资源
最近更新 更多