我必须根据某些条件执行一组操作,例如从数据库中获取数据,每次查询大约需要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,否则它应该停止。 所有这一切我都需要根据条件来做。
答案 0 :(得分:2)
这是我的解决方案
这是我为测试你的场景而创建的假类。如您所见,方法getAllDetails
确实模拟了您的数据库访问。
它等待10秒,然后仅在输入参数为true
时返回40
。这样我们就可以在最坏的情况下测试这段代码,因为所有的调用都需要完成。
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
}
}
此同步方法接收Int
作为参数,并执行10个并发调用ConnectedDevices.getAllDetails
。每次调用都会执行startingIndex
添加到delta
(delta
从0
转到9
。
将结果同步放入同步队列中,numProcessed
安全地增加。如果found
为true
,那么"中奖"返回索引(startingIndex + delta
)。
如果found
永远不会变为true
,则会返回nil
。
这是asych
方法。这是一个简单的for loop
,其中group
变量填充了1
,然后是11
,然后是21
,最后是31
。< / p>
每次调用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())")
}
}
}
对ConnectedDevices.getAllDetails(...)
的40次连续调用需要40 * 10 = 400 seconds
。
在未启用任何优化的iPhone模拟器中,此代码需要大约120 seconds
。
希望这就是你所需要的。
numProcessed
,我也会增加true
。isConditionTrue
的目的,所以我删除了它。