按顺序执行异步操作的正确方法
Correct way to perform async operations sequentially
我需要对数组中的每个元素执行一个异步操作,一次一个。此操作回调主队列。
func fetchResults(for: array, completion: () -> Void) {
var results: [OtherObject]: []
let queue = DispatchQueue(label: "Serial Queue")
queue.sync {
let group = DispatchGroup()
for object in array {
group.enter()
WebService().fetch(for: object) { result in
// Calls back on main queue
// Handle result
results.append(something)
group.leave()
}
group.wait()
}
}
print(results) // Never reached
completion()
}
WebService 调用没有回调 - 我认为这告诉我主队列被阻塞,但我不明白为什么。
您应该使用 group.notify()
而不是 group.wait()
,因为后者是同步的阻塞操作。
如果您只分派一个工作项一次,我也看不到分派到队列的意义。
func fetchResults(for: array, completion: () -> Void) {
var results: [OtherObject]: []
let group = DispatchGroup()
for object in array {
group.enter()
WebService().fetch(for: object) { result in
// Calls back on main queue
// Handle result
results.append(something)
group.leave()
}
}
group.notify(queue: DispatchQueue.main) {
print(results)
completion()
}
}
也许这只是一个打字错误,但基本上不会 运行 排队 sync
hronously。
然后在循环外 (!) 使用 notify
而不是 wait
并在队列中打印 results
。
queue.async {
let group = DispatchGroup()
for object in array {
group.enter()
WebService().fetch(for: object) { result in
// Calls back on main queue
// Handle result
results.append(something)
group.leave()
}
}
group.notify(queue: DispatchQueue.main) {
print(results)
completion()
}
}
我不认为您的主队列已锁定,否则您的应用程序可能会无限加载,就好像它崩溃了一样(在 MacOS 中是肯定的)。
以下是对我有用的方法,也许它会有所帮助:
class func synchronize(completion: @escaping (_ error: Bool) -> Void) {
DispatchQueue.global(qos: .background).async {
// Background Thread
var error = false
let group = DispatchGroup()
synchronizeObject1(group: group){ error = true }
synchronizeObject2(group: group){ error = true }
synchronizeObject3(group: group){ error = true }
group.wait() // will wait for everyone to sync
DispatchQueue.main.async {
// Run UI Updates or call completion block
completion(error)
}
}
}
class func synchronizeObject1(group: DispatchGroup, errorHandler: @escaping () -> Void){
group.enter()
WebservicesController.shared.getAllObjects1() { _ in
// Do My stuff
// Note: if an error occures I call errorHandler()
group.leave()
}
}
如果我要说,它可能来自 queue.sync
而不是 queue.async
。但我不是异步调用方面的专家。
希望对您有所帮助
我需要对数组中的每个元素执行一个异步操作,一次一个。此操作回调主队列。
func fetchResults(for: array, completion: () -> Void) {
var results: [OtherObject]: []
let queue = DispatchQueue(label: "Serial Queue")
queue.sync {
let group = DispatchGroup()
for object in array {
group.enter()
WebService().fetch(for: object) { result in
// Calls back on main queue
// Handle result
results.append(something)
group.leave()
}
group.wait()
}
}
print(results) // Never reached
completion()
}
WebService 调用没有回调 - 我认为这告诉我主队列被阻塞,但我不明白为什么。
您应该使用 group.notify()
而不是 group.wait()
,因为后者是同步的阻塞操作。
如果您只分派一个工作项一次,我也看不到分派到队列的意义。
func fetchResults(for: array, completion: () -> Void) {
var results: [OtherObject]: []
let group = DispatchGroup()
for object in array {
group.enter()
WebService().fetch(for: object) { result in
// Calls back on main queue
// Handle result
results.append(something)
group.leave()
}
}
group.notify(queue: DispatchQueue.main) {
print(results)
completion()
}
}
也许这只是一个打字错误,但基本上不会 运行 排队 sync
hronously。
然后在循环外 (!) 使用 notify
而不是 wait
并在队列中打印 results
。
queue.async {
let group = DispatchGroup()
for object in array {
group.enter()
WebService().fetch(for: object) { result in
// Calls back on main queue
// Handle result
results.append(something)
group.leave()
}
}
group.notify(queue: DispatchQueue.main) {
print(results)
completion()
}
}
我不认为您的主队列已锁定,否则您的应用程序可能会无限加载,就好像它崩溃了一样(在 MacOS 中是肯定的)。
以下是对我有用的方法,也许它会有所帮助:
class func synchronize(completion: @escaping (_ error: Bool) -> Void) {
DispatchQueue.global(qos: .background).async {
// Background Thread
var error = false
let group = DispatchGroup()
synchronizeObject1(group: group){ error = true }
synchronizeObject2(group: group){ error = true }
synchronizeObject3(group: group){ error = true }
group.wait() // will wait for everyone to sync
DispatchQueue.main.async {
// Run UI Updates or call completion block
completion(error)
}
}
}
class func synchronizeObject1(group: DispatchGroup, errorHandler: @escaping () -> Void){
group.enter()
WebservicesController.shared.getAllObjects1() { _ in
// Do My stuff
// Note: if an error occures I call errorHandler()
group.leave()
}
}
如果我要说,它可能来自 queue.sync
而不是 queue.async
。但我不是异步调用方面的专家。
希望对您有所帮助