6

I'm learning about Apple's GCD, and watching the video Concurrent Programming With GCD in Swift 3.

At 16:00 in this video, a flag for DispatchWorkItem is described called .wait, and the functionality and diagram both show exactly what I thought myQueue.sync(execute:) was for.

.wait diagram

So, my question is; what is the difference between:

myQueue.sync { sleep(1); print("sync") }

And:

myQueue.async(flags: .wait) { sleep(1); print("wait") }
// NOTE: This syntax doesn't compile, I'm not sure where the `.wait` flag moved to.
// `.wait` Seems not to be in the DispatchWorkItemFlags enum.

Seems like both approaches block the current thread while they wait for the named queue to:

  1. Finish any current or prior work (if serial)
  2. Complete the given block/work item

My understanding of this must be off somewhere, what am I missing?

SimplGy
  • 20,079
  • 15
  • 107
  • 144

1 Answers1

9

.wait is not a flag in DispatchWorkItemFlags, and that is why your code

myQueue.async(flags: .wait) { sleep(1); print("wait") }

does not compile.

wait() is a method of DispatchWorkItem and just a wrapper for dispatch_block_wait().

/*!
 * @function dispatch_block_wait
 *
 * @abstract
 * Wait synchronously until execution of the specified dispatch block object has
 * completed or until the specified timeout has elapsed.

Simple example:

let myQueue = DispatchQueue(label: "my.queue", attributes: .concurrent)
let workItem = DispatchWorkItem {
    sleep(1)
    print("done")
}
myQueue.async(execute: workItem)
print("before waiting")
workItem.wait()
print("after waiting")

dispatchMain()
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thanks. Seems like it gives you a little more granularity of control than `sync` then. What is `dispatchMain()` doing? – SimplGy Jun 29 '16 at 19:48
  • @SimplGy: https://developer.apple.com/reference/dispatch/1452860-dispatch_main. You need in in programs without a runloop (such as command-line programs) to keep GCD running. In a Playground you achieve the same effect (I think) with `PlaygroundPage.current.needsIndefiniteExecution = true` (http://stackoverflow.com/questions/24058336/how-do-i-run-asynchronous-callbacks-in-playground) – Martin R Jun 29 '16 at 20:00
  • @MartinR Thank you! A small question: what if the code inside the `workItem` block is asynchronous? For example the `SKTextureAtlas`'s `preload(completionHandler:)`. How can we ensure that the `workItem` will wait for that code to finish and only then mark itself as completed? – damirstuhec Nov 24 '16 at 12:15
  • @damirstuhec: A DispatchGroup might be what you are looking for. – Martin R Nov 24 '16 at 12:20
  • @MartinR Not sure if `DispatchGroup` is what I need. Isn't the `DispatchGroup` for grouping the `DispatchQueue`'s to get notified when they are all done with the tasks in their queues? I'm just looking for a way to have a async block of code executed inside of the `DispatchWorkItem` which should wait for it to be finished. – damirstuhec Nov 24 '16 at 12:24
  • @MartinR Also, `DispatchGroup` is iOS 10 only. – damirstuhec Nov 24 '16 at 12:42
  • @damirstuhec: No, DispatchGroup is Swift 3. It is dispatch_group_t in Swift 1+2. – Martin R Nov 24 '16 at 12:53
  • @MartinR True, but that still doesn't answer my question. – damirstuhec Nov 24 '16 at 12:54
  • @damirstuhec: I would suggest that you ask a new question for your problem, this should not be handled in comments. – Martin R Nov 24 '16 at 13:01