根据 swift 中的某些条件执行同时操作

perform simultaneous operations based on the some conditions in swift

我必须根据某些条件执行一组操作,例如从数据库中获取数据,每次查询大约需要 10 秒(ConnectedDevices.getAllDetails() 需要 10 秒才能执行,return 结果)。

这可能类似于以下问题 但就我而言,我需要按以下代码所示批量执行操作:

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 class

这是我为了测试你的场景而创建的假 class。如您所见,方法 getAllDetails 确实模拟了您的数据库访问。 它等待 10 秒,然后仅当输入参数为 40 时 returns true。这样我们就可以在最坏的情况下测试这段代码,因为所有的调用都需要完成。

class ConnectedDevices {
    class func getAllDetails(i:Int) -> Bool {
        sleep(10)
        return i == 40
    }
}

装载机class

这是将与 Grand Central Dispatch 交互的 class。

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 添加到 deltadelta09)。

结果被同步放入同步队列,其中 numProcessed 是安全增加的。如果 foundtrue 那么 "winning" 索引 (startingIndex + delta) 是 returned.

如果 found 永远不会变成 true 那么 nil 就是 returned.

搜索()

这是一个asych方法。这是一个简单的 for loop,其中 group 变量填充有 1,然后是 11,然后是 21,最后是 31.

每次调用search10。如果它确实 return 和 Int 值被传递给 completion 闭包,否则循环继续。

如果从 search10 执行的 4 个循环没有值 return,则 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 seconds.

在我的 iPhone 没有启用任何优化的模拟器中,此代码需要大约 120 seconds

希望这是你需要的。

P.S.

  1. 请注意,如果当前结果是 true,我也会增加 numProcessed
  2. 我没有找到 isConditionTrue 的用途,所以我删除了它。