通用大中央调度
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?") }
我的代码设置如下。据我了解,队列 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?") }