通用大中央调度

Generic Grand Central Dispatch

我的代码设置如下。据我了解,队列 1 应该 完成所有操作,然后移至队列 2。但是,一旦我的异步操作开始,queue2 就会开始。这违背了 GCD 的目的……我做错了什么?这输出:

完成了吗
队列 2
然后一段时间后,从图像下载打印成功

..我想说清楚,如果我在 queue1 中放入其他代码,例如 print("test") 或循环 0..10 打印 i,所有这些操作将在移动之前完成到队列 2。似乎异步下载搞砸了,我该如何解决这个问题?任何地方都没有文档,我使用了来自 AppCoda http://www.appcoda.com/grand-central-dispatch/

的非常有用的指南
    let queue1 = DispatchQueue(label: "com.matt.myqueue1")
    let queue2 = DispatchQueue(label: "com.matt.myqueue2")
    let group1 = DispatchGroup()
    let group2 = DispatchGroup()

    let item = DispatchWorkItem{
        // async stuff happening like downloading an image  
        // print success if image downloads       
    }

    queue1.sync(execute: item)

    item.notify(queue1, execute: {
        print("did this finish?")
    })


    queue2.sync {
        print("queue2")
    }

所有内容最初都从主队列排队,但是在某些时候您从主队列切换到后台队列,您不应该期望同步队列会等待 另一个[排队的内容] =35=]排队。它们无关紧要。如果是这样,那么永远,永远,不管怎样,一切都是等待运行.*

这就是我看到的情况。

队列 1 很高兴地完成了,它通过将 item 排入另一个队列 完成了它应该做的所有事情 <-- 这就是它应该做的所有事情。由于 'async stuff' 是异步的...它不会等待它完成。 <-- 实际上,如果你在异步中使用断点,你会看到断点会跳转到 } ,这意味着它们不会等待后台队列,它们只是跳到队列的末尾,因为它们不再在主线程上

然后因为它是一个同步队列,所以它一直等到它完成。一旦完成,它将通过它的 notify...现在这里是它变得棘手的地方:取决于您在异步中执行的操作的速度...'print success' 将首先被调用或“queue2”这里显然 queue2 returning/finishing 更快。

与您在 this 答案中看到的相似。


*:一个妈妈(主队列)告诉它 child1 到你的房间,把 book1 带回来,然后告诉 child2 到你的房间,把 book2 带回来,然后告诉 child3 到你的房间,把书 3 带回来。每个 child 来自其自己的队列(不是母亲的队列)运行。

妈妈 不等 child1 回来...所以它可以告诉 child2 走。妈妈只说child1 go...然后child2 go...然后child3 go.

然而 child2 在 child 1 之前没有被告知(去),child3 在 child2 或 child1 之前也没有被告知(去) <-- 这是因为主队列的 serial-ness。它们按顺序发送,但它们的完成顺序取决于每个 child/queue 完成的速度

let item = DispatchWorkItem{
    // async stuff happening like downloading an image  
    // print success if image downloads       
}

好的,定义了它,但还没有 运行。

queue1.sync(execute: item)

执行item启动它的异步事件。之后立即return。这里什么都没有说 "wait for those unrelated asynchronous events to complete." 系统甚至没有办法知道您调用的函数内部还有其他异步调用。它如何知道 object.doit() 是否包含异步调用(以及这些调用是否是您打算等待的异步调用)?它只知道什么时候 item returns,继续。

这就是 group1 的用途(您似乎没有将其用于任何用途)。在这些 "async stuff happening" 内部的某个地方,您应该通过离开组来告诉系统它已完成。 (我不知道 group2 是干什么用的,也没用过。)

item.notify(queue1, execute: {
    print("did this finish?")
})

item 已经完成。我们知道它 已经 已经完成,因为它是 运行 和 sync,并且 return 直到它的项目完成。所以这个块将立即安排在 queue1.

queue2.sync {
    print("queue2")
}

完全不相关并且可以 运行 在 "did this finish" 代码之前或之后,我们在 queue2.

上安排了一个块

您的意思可能是:

let queue1 = DispatchQueue(label: "com.matt.myqueue1")
let group1 = DispatchGroup()

group1.enter()

// Kick off async stuff.
// These usually return quickly, so there's no need for your own queue.
// At some point, when you want to say this is "done", often in some 
// completion handler, you call group1.leave(), for example:
       ... completionHandler: { group1.leave() }

// When all that finishes, print
group.notify(queue: queue1) { print("did this finish?") }