ios - 如何在 Swift 3 中处理组等待结果

标签 ios swift multithreading swift3 grand-central-dispatch

我在 playground 中尝试遵循代码,但它们似乎没有按我预期的那样工作。

在我的 mac 上,两次 group_async 操作总共导致大约 5~6 秒。

  • 当我将超时时间设置为 DispatchTime.now() + 10 时,“测试返回”和“完成”都会被打印出来。
  • 当我将超时时间设置为 DispatchTime.now() + 1(某些值使组超时)时,除了两个 group_async 操作中的打印代码外,什么都没有打印。

我想要的是暂停组并在超时时进行一些清理,并在组成功完成后进行一些其他进一步的操作。任何建议表示赞赏。谢谢。

import Dispatch
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue.global(qos: .utility)

func test() {
    let group = DispatchGroup()
    __dispatch_group_async(group, queue) {
        var a = [String]()
        for i in 1...999 {
            a.append(String(i))
            print("appending array a...")
        }
        print("a finished")
    }

    __dispatch_group_async(group, queue) {
        var b = [String]()
        for i in 1...999 {
            b.append(String(i))
            print("appending array b...")
        }
        print("b finished")
    }

    let result = group.wait(timeout: DispatchTime.now() + 10)
    if result == .timedOut {
        group.suspend()
        print("timed out")
    }
    print("test returns")
}


queue.async {
    test()
    print("done")
}

最佳答案

此代码片段提出了各种不同的问题:

  1. 我注意到 playground 和您在应用程序中运行它时的行为略有不同。我怀疑这是 PlaygroundPage 和 GCD 的 needsIndefiniteExecution 的一些特质。我建议在应用程序中对此进行测试。考虑到我在下面提出的要点,当我从应用程序运行它时,它按预期工作。

  2. 我注意到您采用了这种模式:

    __dispatch_group_async(group, queue) {
        ...
    }
    

    我建议:

    queue.async(group: group) {
        ...
    }
    
  3. 您正在执行 group.suspend()。一些注意事项:

    • 一个挂起队列,而不是组。

    • 如果您曾经调用过 suspend(),请确保您在某处调用了相应的 resume()

    • 另外,请记住 suspend() 会阻止 future 的 block 开始,但它不会对可能已经在运行的 block 做任何事情。如果您想停止已经在运行的 block ,您可能想要取消它们。

    • 最后,请注意您只能挂起您创建的队列和源。您不能(也不应该)暂停全局队列。

  4. 我还注意到您在调度 test() 调用的同一个队列上使用了 wait。在这种情况下,您可以摆脱它,因为它是一个并发队列,但这种模式会引发死锁。如果可以的话,我建议完全避免 wait,当然也不要在调用它的同一个队列上执行它。同样,这在这里不是问题,但它是一种模式,将来可能会给您带来麻烦。

    就个人而言,我可能倾向于使用 notify 而不是 wait 来触发代码块在两个分派(dispatch) block 完成时运行。这消除了任何死锁风险。如果我想让一段代码在一定时间后运行(即超时过程),我可能会使用计时器来触发一些清理过程,以防这两个代码块仍在运行(可能取消它们;参见 How to stop a DispatchWorkItem in GCD? ).

关于ios - 如何在 Swift 3 中处理组等待结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39970411/

相关文章:

ios - 阴影未显示在 UIView 上

.net - 尝试从后台线程更新 UI : Why does it sometimes throw and sometimes just do nothing?

ios - 如何在特定图像旋转时触发事件?

swift - Poisson Disk Generator 排除了四个 View 象限中的三个

ios - objective c 以编程方式解除分配/释放对象

swift - 如何使tableView中单元格中的图像显示一致?

java - Java中如何向线程共享变量?

Python、solr 海量查询 : need some suggestions

ios - 我在 MacOSX 10.7.x 上找不到 libtool 命令

ios - MFMailComposeViewController 显示定位