- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有这个代码:
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, animated: true, completion: nil)
} else {
let timeOutAlertController = UIAlertController(title: "Time Out", message: "Failed to request service, reason: \"Time Out\"", preferredStyle: UIAlertControllerStyle.alert)
let gotItAction = UIAlertAction(title: "Got it", style: UIAlertActionStyle.cancel, handler: nil)
timeOutAlertController.addAction(gotItAction)
self.present(timeOutAlertController, animated: true, completion: nil)
}
}
每次让dispatchGroup等待,总是返回timeout。怎么了?我将它设置为 10000000000 纳秒,应该是 10 秒吧?我的请求确实在 10 秒前得到了回复。
最佳答案
几个想法:
正如 rmaddy 所说,如果你想等待 10 秒,正确的语法是:
let waitResult = dispatchGroup.wait(timeout: .now() + 10)
你的语法根本不会等待,而且看起来会立即超时。
你根本不应该等待。
首先,你应该永远阻塞主线程。在最坏的情况下,如果您在错误的时间执行此操作,您的应用程序可能会被看门狗进程杀死。充其量,这是一个可怕的用户体验(即应用程序对最终用户来说似乎完全卡住)。
其次,根据 POSTRequest
的实现方式,您可能会引入新问题。具体来说,如果 POSTRequest
在主队列上调用其完成处理程序(例如,Alamofire 等网络库的默认行为),您可能会死锁,直到主线程上的 wait
超时到期.如果你要等待(无论如何你都不应该这样做),你要确保你永远不会在你的完成处理程序将使用的同一个队列上等待。
请注意,如果完成处理程序不在您正在等待的同一个队列上运行,则不会有死锁风险,但您仍然会遇到我之前提到的问题,即您正在阻塞主线程,这应始终避免。
您应该改为将所有代码移入闭包内。如果该闭包在后台线程上运行,请确保 DispatchQueue.main.async { ... }
将其分派(dispatch)回主队列。
因此,正确的模式类似于以下内容。
如果您希望您的请求在 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
构建到请求中。
然后,确保您的 UIAlertAction
启动请求并将所有处理简单地放在 POSTRequest
之后的 completionHandler
中,从而消除了任何调度组等待或类似的事情的需要:
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", message: "Failed to request service, reason: \"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)
}
}
}
这样,没有线程被阻塞。
关于swift - 为什么我的 DispatchGroup 的等待总是超时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46008848/
我想知道以下情况。 我在一个函数中有一个 DispatchGroup。现在我在后台线程上进入组并调用 wait()。 func test() { let group = DispatchGrou
下面的代码我用来进行并发 API调用。不知怎的,这个方法返回多次。我已经在没有 DispatchGroup 的情况下进行了测试,它按预期工作。帮我找出为什么它多次调用。 我的代码片段: fu
是否可以从另一个类访问 DispatchGroup?假设我在类 Loginfunctions.swift 中有以下函数(在 func 中定义了 var loginQueue = DispatchGro
我正在尝试使用 Firebase 身份验证来注册用户。当用户注册时,我希望将他们添加到我的 Users 中Firestore 中的集合以及 Users授权部分。 createUser(withEmai
我正在尝试链接两个调度组,但我的代码总是在随机位置崩溃。 我的功能是这样的: func getAllActivities(userUID: String, _ completionHandler: @
我想使用 DisaptchGroup 在遍历并将元素追加到数组后调用 func。 这是 firebase 节点的样子 { "tags": { "NewYork":
enter code here我用调度组尝试了很多东西,但我无法获得稳定的结果。自从我的服务器以来,我使用 Alamofire 获取数据。我在 Helper 类中编写了一个函数,并在 AppDeleg
我目前有一个数组,它遍历图像路径的值,并希望在第一个 for 循环中异步检索这些图像。我试过使用两个调度组,但总是在检索图像之前返回完成处理程序。 static func getAllEntriesW
我创建了一个 DispatchGroup 并运行了 2 个异步任务。一个在 main 上,另一个在 global() 上。 据我所知,DispatchGroup.notify 的 block 应该在所
因此,我花了一些时间尝试让 DispatchGroup 在长时间的异步操作完成之前阻止 for 循环迭代。我发现的大多数示例都相当简单明了,但我似乎无法让我的简单测试用例按预期工作。 let grou
我有两个函数(或任务),我想一个接一个地运行,我正在使用 DispatchGroup 来跟踪它们并在它们完成时通知我。现在它们正在主线程中完成,但我想在后台线程中运行这些任务。我将如何去做呢?我尝试了
以下是否会产生可能的竞争条件? let syncGroup = DispatchGroup() var tempData: [Int] for index in 1...10 { sync
我必须停止我的代码一秒钟,以便在继续之前同步服务器数据库。 下面的所有代码片段都是从主线程运行的。 我首先使用了这个: // code 1 DispatchQueue.main.asyncAfter(
我正在进行两个异步网络调用,并且想使用一个 Dispatch Group 来等待调用完成然后恢复。我的程序卡住了。 class CommentRatingViewController: UIViewC
我想让对服务的调用同步,因为我希望我的调用返回已使用泛型映射的对象。 这是代码: func execute(request: HttpRequest, responseType: T.Type) th
我遇到一种情况,我需要等待一组任务完成才能执行某些 UI 渲染代码。 其中一些任务是网络请求,它们始终会完成并离开调度组。然而,有些不是网络请求,可能会也可能不会完成。如果一项任务未完成,并且离开的调
在使用异步递归调用 API 时,我无法理解如何使用 GCD。 下面是三个类似方法之一,包含相同的逻辑,只是针对不同的数据和 API 端点。如果没有下一页请求,该方法应该完成并且下一个方法应该开始。 我
我在理解或使用 Dispatchgroup 时遇到问题。我已经阅读了很多关于它们的内容,但是大多数示例/文档都非常模糊或者与我想做的不一样,但是每次我提到我的问题时,每个人都说“使用调度组!”。 这是
问题描述: 我想通过“DispatchGroup”执行一系列异步任务,当所有这些任务完成时它返回结果。另外,我想设置限制进程的超时时间,到时候把成功的结果发给我。我使用了以下结构: 代码块 let m
在下面的代码中,附加到数组是否安全?是否保证维持秩序? let processedData: [SomeType] = [] let dispatchGroup = DispatchGroup() f
我是一名优秀的程序员,十分优秀!