Swift DispatchSemaphore 正在冻结应用程序

Posted

技术标签:

【中文标题】Swift DispatchSemaphore 正在冻结应用程序【英文标题】:Swift DispatchSemaphore is freezing the application 【发布时间】:2021-08-24 08:16:14 【问题描述】:

我尝试使用 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 相关的任务从能够并发运行中受益匪浅。 每个响应都依赖于前一个响应,因此我使用信号量 或者我们可以通过其他方式实现这一目标吗? 【参考方案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() 阻塞整个进程 你提到的上面的代码你使用的是两个不同的信号量吗?

以上是关于Swift DispatchSemaphore 正在冻结应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何将 DispatchSemaphore 与 Alamofire 和 SwiftyJSON 一起使用?

Swift Async - Task.detached 在哪个线程上运行?

如何正确使用信号灯同步 Alamofire 请求 Swift4 的主线程?

赵雅智_Swift_swift凝视

《纽约时报》将采访中国Taylor Swift粉丝会

Swift 3委托函数未调用