繁体   English   中英

Swift 3 DispatchGroup单成功DispatchWorkItem

[英]Swift 3 DispatchGroup single success DispatchWorkItem

这是交易。 我试图在树上走。 但是要同时进行。 因此,每次我走到一个节点上时,我都需要同时走动它的所有节点,依此类推。 但。 我不想等待整个DispatchGroup完成以获取结果,因为在Big O中这是最坏的情况。相反,我想取消所有其他DispatchWorkItems并在后续的工作组中保留它们。 试图通过计算结束的任务来做到这一点。 显然我在做错事或误解了如何使用它。 下面的代码仅用于示例目的和测试想法。 考虑到现实情况,您可以在DispatchWorkItem中递归调用树的当前节点的另一个handle函数。

func handle(completion: @escaping (Int) -> Void) {
    var result: Int = 0


    var count = 7
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "q", attributes: .concurrent)

    var items = [DispatchWorkItem]()

    let item1 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...1000 { continue }
        count -= 1
        group.leave()
        print("left 1")
    }
    let item2 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...2000 { continue }
        count -= 1
        group.leave()
        print("left 2")
    }
    let item3 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...6000 { continue }
        count -= 1
        group.leave()
        print("left 3")
    }
    let item4 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...3000 { continue }
        result = 42

        items.forEach { $0.cancel() }

        for _ in 0..<count {
            group.leave()
        }

        print("ok; left 4")
    }
    let item5 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...50000 { continue }
        count -= 1

        group.leave()
        print("left 5")
    }
    let item6 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...6000 { continue }
        count -= 1
        group.leave()
        print("left 6")
    }
    let item7 = DispatchWorkItem(flags: .inheritQoS) {
        for _ in 0...8000 { continue }
        count -= 1
        group.leave()
        print("left 7")
    }

    items.append(item1)
    items.append(item2)
    items.append(item3)
    items.append(item4)
    items.append(item5)
    items.append(item6)
    items.append(item7)

    for item in items {
        group.enter()
        queue.async(execute: item)
    }

    group.notify(queue: queue) { 
        return
    }
}

test() {
    handle { result in
        print(result)
    }

}

您不能一次从多个线程读取和写入计数变量。 您需要对互斥锁进行计数。 您遇到不稳定的情况,试图从多个线程访问和/或更改计数。 另外,您应该设计为根本不需要计数。

一些想法:

  1. 如果要取消耗时的任务,则需要定期检查isCancelled 参见https://stackoverflow.com/a/38372384/1271826

  2. 如果要更新多个线程中的countitems ,则必须同步该交互(例如,使用锁或专用串行队列)。 IntArray不是线程安全的,因此您必须自己进行管理。

  3. 跟踪count并使用DispatchGroup并跟踪您自己的DispatchWorkItem引用集合将需要一些工作。 操作队列使您摆脱了所有这些。 话虽这么说,如果需要最大的效率,那么也许您想留在调度队列中,但这只是很多工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM