swift – 为什么我的DispatchGroup的等待总是超时?
我有这个代码:
let goAheadAction = UIAlertAction(title: "Go Ahead",style: .default) { _ in let dispatchGroup = DispatchGroup() dispatchGroup.enter() Server.POSTRequest(accessPoint: "/UserServices/forgotPassword",params:["emailAddress" : self.emailAddressTextField.text!],handler: { (data: Data?,response: URLResponse?,error: Error?) -> Void in // TODO: Only considered successful case /*let confirmAlertController = UIAlertController(title: "Email been sent",message: "Please check your mailbox",preferredStyle: UIAlertControllerStyle.alert) self.present(confirmAlertController,animated: true,completion: nil)*/ dispatchGroup.leave() }) let waitResult = dispatchGroup.wait(timeout: DispatchTime(uptimeNanoseconds: 10000000000)) if waitResult == .success { let emailSentAlertController = UIAlertController(title: "Email Sent",message: "We've sent an password reset link to "(self.emailAddressTextField.text!)"",preferredStyle: UIAlertControllerStyle.alert) let gotItAction = UIAlertAction(title: "Got it",style: UIAlertActionStyle.cancel,handler: nil) emailSentAlertController.addAction(gotItAction) self.present(emailSentAlertController,completion: nil) } else { let timeOutAlertController = UIAlertController(title: "Time Out",message: "Failed to request service,reason: "Time Out"",handler: nil) timeOutAlertController.addAction(gotItAction) self.present(timeOutAlertController,completion: nil) } } 每次我让dispatchGroup等待,它总是返回超时.怎么了?我把它设置为10000000000纳秒,这应该是10秒吧?我的要求确实在10秒之前回来了.
几点想法:
>正如rmaddy所说,如果你想等待10秒,正确的语法将是: let waitResult = dispatchGroup.wait(timeout: .now() + 10) 你的语法根本不会等待,看起来它会立即超时. 首先,你永远不应该阻止主线程.在最坏的情况下,如果您在错误的时间执行此操作,您可能会被监视程序进程杀死.充其量,它是一个可怕的用户体验(即应用程序似乎完全冻结给最终用户). 其次,根据POSTRequest的实现方式,您可能会引入一个新问题.具体来说,如果POSTRequest在主队列上调用其完成处理程序(例如Alamofire等网络库的默认行为),则可能会死锁,直到主线程上的等待超时到期为止.如果您要等待(无论如何都不应该这样做),您需要确保永远不要等待完成处理程序将使用的同一队列. 注意,如果完成处理程序没有在您正在等待的同一队列上运行,则没有死锁风险,但您仍然遇到我之前提到的问题,即您正在阻塞主线程,这应该始终是避免. 您应该在闭包内移动所有代码.如果该闭包在后台线程上运行,请确保将DispatchQueue.main.async {…}发送回主队列. 因此,正确的模式类似于以下内容. >如果您希望请求在10秒后超时,请将其构建到原始请求中.注意timeoutInterval: class func POSTRequest(accessPoint: String,params: [String: String]?,completionHandler: @escaping (Data?,URLResponse?,Error?) -> Void) { let url = URL(string: baseURLString)! .appendingPathComponent(accessPoint) let request = URLRequest(url: url,timeoutInterval: 10) URLSession.shared.dataTask(with: request,completionHandler: completionHandler) } 显然,你可能在POSTRequest中做了其他事情,所以不要迷失在那里的细节.关键是在请求中构建timeoutInterval. let goAheadAction = UIAlertAction(title: "Go Ahead",style: .default) { _ in let email = self.emailAddressTextField.text! let parameters = ["emailAddress": email] Server.POSTRequest(accessPoint: "/UserServices/forgotPassword",params: parameters) { data,response,error in DispatchQueue.main.async { guard error == nil else { let alert = UIAlertController(title: "Time Out",preferredStyle: .alert) alert.addAction( UIAlertAction(title: "Got it",style: .cancel)) self.present(alert,animated: true) return } let alert = UIAlertController(title: "Email Sent",message: "We've sent an password reset link to "(email)"",preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Got it",style: .cancel)) self.present(alert,animated: true) } } } 这样,没有线程被阻止. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0,
- ListView获取选中和长按菜单对应的item的_id值
- 如何在SQLite中创建自增字段
- xcode – 如何检查AVPlayer是视频还是音频?
- 利用正则表达式统计代码中的(代码行数,注释行数,空白行数
- SQlite数据库的C编程接口(七) 数据库锁定(Database Lock
- Ruby:如何动态创建现有类的子类?
- objective-c – Core Data查询中fetchLimit和fetchOffset的
- oop – 单一责任原则 – 一个很难看的例子?
- flex 定时器 flash.util.Timer类