我必须根据某些条件执行一组操作,例如从数据库中获取数据,每次查询大约需要 10 秒(ConnectedDevices.getAllDetails() 需要 10 秒才能执行并返回结果)。
这可能类似于下面的问题 optimized way to search a device ip address within a range in iphone 但就我而言,我需要按以下代码所示批量执行操作:
var isConditionTrue = false
var numProcessed = 0
let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
// case 1
for i in 1...10 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 2
for i in 11...20 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
// case 3
for i in 21...30 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !ieachDBValue {
numProcessed++
}
}
}
}
// case 4
for i in 31...40 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
let eachDBValue = ConnectedDevices.getAllDetails(i)
dispatch_async(dbQueue) {
if !eachDBValue {
numProcessed++
}
}
}
}
因此,如果在案例 1 中,如果 1 到 10 的结果为假,那么它应该转到案例 2。如果任何实例的结果为真.. 它不应该执行任何案例 2、3、4。
与情况 2 类似,如果 1 到 10 的结果为假,那么它应该转到情况 3,否则它应该停止。 所有这些我都需要根据条件来做。
最佳答案
这是我的解决方案
伪造的 ConnectedDevices 类
这是我为测试您的场景而创建的假类。如您所见,getAllDetails
方法确实模拟了您的数据库访问。
它等待 10 秒,然后仅当输入参数为 40
时才返回 true
。这样我们就可以在最坏的情况下测试这段代码,因为所有的调用都需要完成。
class ConnectedDevices {
class func getAllDetails(i:Int) -> Bool {
sleep(10)
return i == 40
}
}
加载器类
这是将与 Grand Central Dispatch
交互的类。
class Loader {
private var numProcessed = 0
private let dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_SERIAL)
private let utilityQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
func search(completion:(result:Int?)->()) {
dispatch_async(utilityQueue) {
for group in [1, 11, 21, 31] {
if let indexFound = self.search10(group) {
completion(result: indexFound)
return
}
}
completion(result: nil)
}
}
private func search10(startingIndex:Int) -> Int? {
var indexFound : Int?
dispatch_apply(10, utilityQueue) { (delta) -> () in
let found = ConnectedDevices.getAllDetails(startingIndex + delta)
dispatch_sync(self.dbQueue) {
self.numProcessed++ // this is increased anyway
if found {
indexFound = startingIndex + delta
}
}
}
return indexFound
}
}
search10(startingIndex:Int)
此同步方法接收一个 Int
作为参数,并执行 10 个对 ConnectedDevices.getAllDetails
的并发调用。每次调用都将 startingIndex
添加到 delta
(delta
从 0
到 9
).
结果被同步放入同步队列,其中 numProcessed
安全增加。如果 found
为 true
,则返回“获胜”索引 (startingIndex + delta
)。
如果 found
永远不会变为 true
,则返回 nil
。
搜索()
这是一个asych
方法。这是一个简单的 for 循环
,其中 group
变量填充有 1
,然后是 11
,然后是 21
最后是 31
。
每次 search10
被调用。如果它确实返回了 Int
,则该值将传递给 completion
闭包,否则循环会继续。
如果执行了 4 个循环而 search10
没有返回任何值,则 nil
将传递给 completion
闭包。
用法
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
debugPrintln("Begin: \(NSDate())")
Loader().search { (result) -> () in
debugPrintln(result)
debugPrintln("End: \(NSDate())")
}
}
}
测试
40 次连续调用 ConnectedDevices.getAllDetails(...)
需要 40 * 10 = 400 秒
。
在我没有启用任何优化的 iPhone 模拟器中,此代码需要大约 120 秒
。
希望这就是您所需要的。
附言
- 请注意,如果当前结果为
true
,我也会增加numProcessed
。 - 我没有找到
isConditionTrue
的用途,所以我删除了它。
关于ios - 根据某些条件 swift 执行同时操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32460916/