1

I know there are already a lot of posts about dispatch queues, async tasks etc. ,but I can't retrieve a useful explanation out of these posts, because there are too many distractions because of the extra code. I there someone who can give me a clear instruction on how to make Task B start after task A has been finished?

I need some data from Task A in order to run Task B successfully and I know that I have to do something with DispatchQueue.async, but I don't know how exactly.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Sven Cozijn
  • 119
  • 14
  • "Task B start after task A" One after another = Serial. So you want a serial DispatchQueue (this is the default). Do you want to block to wait for A and B to finish, or do you want them to be dispatched asynchronously, and have your program resume without waiting for them to finish? – Alexander Jul 12 '17 at 17:18
  • @Alexander Yes, that is what I need and I want the other code to wait for task A and B since Task A and B gather all data that is required for all other coding. – Sven Cozijn Jul 12 '17 at 17:21
  • So then you want to submit your tasks synchronously (`.sync`), not asynchronously (`.async`) – Alexander Jul 12 '17 at 17:28
  • @Rob "gather all data that is required for all other coding" gave me the impression that he wants to wait for it all to finish before continuing. – Alexander Jul 12 '17 at 17:32
  • @Rob I would put this entire process (A then B) on an async call, and then within that, I would have them be synchronously called. It prevents you from needing crazy numbers of nested completion handlers – Alexander Jul 12 '17 at 18:12

2 Answers2

2

The typical process would be to dispatch asynchronously with async to some serial queue. So, let's say you want some queue for processing images, doing task A and then task B, and then do some UI updates when task B is done, you might do:

let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".images")

queue.async {
    // do task A
}

queue.async { 
    // do task B
}

queue.async {
    // do whatever else is needed after B here

    DispatchQueue.main.async {
        // update model objects and UI here
    }
}

This is a pattern that avoids blocking the main queue, but lets you make sure that you do A and B serially.

Please note, that if either task A or task B are, themselves, asynchronous, the above won't work. (Nor would trying to use sync, if the underlying task was asynchronous.) Other patterns would apply in these cases. But your example is too generic and there are simple too many other possible patterns for us to enumerate them all. If you tell us specifically what task A and B are doing, we could offer more constructive counsel.

Also note that I'd explicitly advise against dispatching synchronously (with sync). Using sync has a certain intuitive appeal, but it is rarely the right approach. Blocking the calling thread (which is what sync does) largely defeats the purpose of having dispatch queue in the first place. The (largely) only reason one should use sync is if you're trying to have thread-safe access to some shared resource. But most of the time, you use dispatch queues explicitly for the purpose of getting some time consuming task off the current thread. So, dispatch A and B async to serial queue, and if you wanted to do something else, C, afterwards, then you'd dispatch that async to the same queue, too.

For a description see Concurrency Programming Guide: Dispatch Queues. The examples are in Objective-C, but all the concepts are the same. You can also go to WWDC videos and search for "GCD", and you'll get a number of great videos that walk through Grand Central Dispatch (the broader term for dispatch queue technologies).

Rob
  • 415,655
  • 72
  • 787
  • 1,044
1

How about something like this?

import Dispatch

let queue = DispatchQueue(label: "My dispatch queue") //TODO: Give better label

let result1 = queue.sync { // "Task A"
    return "result 1"
}

let result2 = queue.sync { // "Task B", which uses result from Task A
    return result1.uppercased()
}

print(result2)
Alexander
  • 59,041
  • 12
  • 98
  • 151