如何停止 DispatchGroup 或 OperationQueue 等待?
How to stop DispatchGroup or OperationQueue waiting?
DispatchGroup
和 OperationQueue
有方法 wait()
和 waitUntilAllOperationsAreFinished()
等待各自队列中的所有操作完成。
但即使我调用 cancelAllOperations
它也只是在每个 运行 操作中更改标志 isCancelled
并阻止队列执行新操作。但它仍在等待操作完成。因此 运行 必须从内部停止操作。但只有当操作是增量的或具有任何类型的内部循环时才有可能。当它只是长外部请求时(例如web请求),没有使用isCancelled
变量。
如果其中一个操作决定所有队列现在都已过时,是否有任何方法可以停止 OperationQueue 或 DispatchGroup 等待操作完成?
实际情况是:将请求映射到响应者列表,并且已知只有一个可以响应。如果发生这种情况,队列应停止等待其他操作完成并解锁线程。
编辑:DispatchGroup 和 OperationQueue 的使用不是强制性的,这些只是我认为合适的工具。
好的,所以我想我想到了一些东西。结果稳定,我刚刚测试过。答案只是一个信号量:)
let semaphore = DispatchSemaphore(value: 0)
let group = DispatchGroup()
let queue = DispatchQueue(label: "map-reduce", qos: .userInitiated, attributes: .concurrent)
let stopAtFirst = true // false for all results to be appended into one array
let values: [U] = <some input values>
let mapper: (U) throws -> T? = <closure>
var result: [T?] = []
for value in values {
queue.async(group: group) {
do {
let res = try mapper(value)
// appending must always be thread-safe, otherwise you end up with race condition and unstable results
DispatchQueue.global().sync {
result.append(res)
}
if stopAtFirst && res != nil {
semaphore.signal()
}
} catch let error {
print("Could not map value \"\(value)\" to mapper \(mapper): \(error)")
}
}
}
group.notify(queue: queue) { // this must be declared exactly after submitting all tasks, otherwise notification fires instantly
semaphore.signal()
}
if semaphore.wait(timeout: .init(secondsFromNow: 5)) == .timedOut {
print("MapReduce timed out on values \(values)")
}
DispatchGroup
和 OperationQueue
有方法 wait()
和 waitUntilAllOperationsAreFinished()
等待各自队列中的所有操作完成。
但即使我调用 cancelAllOperations
它也只是在每个 运行 操作中更改标志 isCancelled
并阻止队列执行新操作。但它仍在等待操作完成。因此 运行 必须从内部停止操作。但只有当操作是增量的或具有任何类型的内部循环时才有可能。当它只是长外部请求时(例如web请求),没有使用isCancelled
变量。
如果其中一个操作决定所有队列现在都已过时,是否有任何方法可以停止 OperationQueue 或 DispatchGroup 等待操作完成?
实际情况是:将请求映射到响应者列表,并且已知只有一个可以响应。如果发生这种情况,队列应停止等待其他操作完成并解锁线程。
编辑:DispatchGroup 和 OperationQueue 的使用不是强制性的,这些只是我认为合适的工具。
好的,所以我想我想到了一些东西。结果稳定,我刚刚测试过。答案只是一个信号量:)
let semaphore = DispatchSemaphore(value: 0)
let group = DispatchGroup()
let queue = DispatchQueue(label: "map-reduce", qos: .userInitiated, attributes: .concurrent)
let stopAtFirst = true // false for all results to be appended into one array
let values: [U] = <some input values>
let mapper: (U) throws -> T? = <closure>
var result: [T?] = []
for value in values {
queue.async(group: group) {
do {
let res = try mapper(value)
// appending must always be thread-safe, otherwise you end up with race condition and unstable results
DispatchQueue.global().sync {
result.append(res)
}
if stopAtFirst && res != nil {
semaphore.signal()
}
} catch let error {
print("Could not map value \"\(value)\" to mapper \(mapper): \(error)")
}
}
}
group.notify(queue: queue) { // this must be declared exactly after submitting all tasks, otherwise notification fires instantly
semaphore.signal()
}
if semaphore.wait(timeout: .init(secondsFromNow: 5)) == .timedOut {
print("MapReduce timed out on values \(values)")
}