How do I use DispatchGroup in background thread?












1















I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


If I use the following code they are run simultaneously but in the background thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.



func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressOne.completedUnitCount = Int64(i * 20)

print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}

func secondFunction(completion: @escaping()->Void){
print(Thread.current)

if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressTwo.completedUnitCount = Int64(i * 20)

print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}


This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.



 @objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}









share|improve this question

























  • When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.

    – George_E
    Dec 29 '18 at 18:12











  • @George_E I don't want them to run simultaneously. I want them to run in the background one after the other.

    – Gustavo Picciuto
    Dec 29 '18 at 18:14













  • Does it work if you use the first block of code with the sync and put both in one DispatchQueue block?

    – George_E
    Dec 29 '18 at 18:18











  • That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.

    – Gustavo Picciuto
    Dec 29 '18 at 18:22













  • @George_E updated question with suggestion.

    – Gustavo Picciuto
    Dec 29 '18 at 18:25
















1















I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


If I use the following code they are run simultaneously but in the background thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.



func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressOne.completedUnitCount = Int64(i * 20)

print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}

func secondFunction(completion: @escaping()->Void){
print(Thread.current)

if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressTwo.completedUnitCount = Int64(i * 20)

print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}


This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.



 @objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}









share|improve this question

























  • When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.

    – George_E
    Dec 29 '18 at 18:12











  • @George_E I don't want them to run simultaneously. I want them to run in the background one after the other.

    – Gustavo Picciuto
    Dec 29 '18 at 18:14













  • Does it work if you use the first block of code with the sync and put both in one DispatchQueue block?

    – George_E
    Dec 29 '18 at 18:18











  • That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.

    – Gustavo Picciuto
    Dec 29 '18 at 18:22













  • @George_E updated question with suggestion.

    – Gustavo Picciuto
    Dec 29 '18 at 18:25














1












1








1








I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


If I use the following code they are run simultaneously but in the background thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.



func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressOne.completedUnitCount = Int64(i * 20)

print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}

func secondFunction(completion: @escaping()->Void){
print(Thread.current)

if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressTwo.completedUnitCount = Int64(i * 20)

print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}


This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.



 @objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}









share|improve this question
















I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


If I use the following code they are run simultaneously but in the background thread.



@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}


I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.



func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressOne.completedUnitCount = Int64(i * 20)

print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}

func secondFunction(completion: @escaping()->Void){
print(Thread.current)

if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)

childProgressTwo.completedUnitCount = Int64(i * 20)

print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}


This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.



 @objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}






swift






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 29 '18 at 18:24







Gustavo Picciuto

















asked Dec 29 '18 at 18:05









Gustavo PicciutoGustavo Picciuto

86




86













  • When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.

    – George_E
    Dec 29 '18 at 18:12











  • @George_E I don't want them to run simultaneously. I want them to run in the background one after the other.

    – Gustavo Picciuto
    Dec 29 '18 at 18:14













  • Does it work if you use the first block of code with the sync and put both in one DispatchQueue block?

    – George_E
    Dec 29 '18 at 18:18











  • That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.

    – Gustavo Picciuto
    Dec 29 '18 at 18:22













  • @George_E updated question with suggestion.

    – Gustavo Picciuto
    Dec 29 '18 at 18:25



















  • When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.

    – George_E
    Dec 29 '18 at 18:12











  • @George_E I don't want them to run simultaneously. I want them to run in the background one after the other.

    – Gustavo Picciuto
    Dec 29 '18 at 18:14













  • Does it work if you use the first block of code with the sync and put both in one DispatchQueue block?

    – George_E
    Dec 29 '18 at 18:18











  • That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.

    – Gustavo Picciuto
    Dec 29 '18 at 18:22













  • @George_E updated question with suggestion.

    – Gustavo Picciuto
    Dec 29 '18 at 18:25

















When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.

– George_E
Dec 29 '18 at 18:12





When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.

– George_E
Dec 29 '18 at 18:12













@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.

– Gustavo Picciuto
Dec 29 '18 at 18:14







@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.

– Gustavo Picciuto
Dec 29 '18 at 18:14















Does it work if you use the first block of code with the sync and put both in one DispatchQueue block?

– George_E
Dec 29 '18 at 18:18





Does it work if you use the first block of code with the sync and put both in one DispatchQueue block?

– George_E
Dec 29 '18 at 18:18













That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.

– Gustavo Picciuto
Dec 29 '18 at 18:22







That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.

– Gustavo Picciuto
Dec 29 '18 at 18:22















@George_E updated question with suggestion.

– Gustavo Picciuto
Dec 29 '18 at 18:25





@George_E updated question with suggestion.

– Gustavo Picciuto
Dec 29 '18 at 18:25












3 Answers
3






active

oldest

votes


















1














Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:



@objc func doWorkFunctions() {
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.secondFunction {
DispatchQueue.main.async {
print("All tasks completed")
}
}
}
}


But assuming you have a good reason for a group here, what you need to do is to use .notify to synchronize them. .notify says "when the group is empty, submit this block to this queue."



@objc func doWorkFunctions(){
let queue = DispatchQueue.global(qos: .background)

taskGroup.enter()
queue.async {
self.firstFunction {
self.taskGroup.leave()
}
}

taskGroup.notify(queue: queue) {
self.taskGroup.enter()

self.secondFunction {
self.taskGroup.leave()
}

self.taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
}


(You probably don't need taskGroup to be an instance property here. You could make it a local variable and have fewer self. references required. Each block has a reference to the group, so it will live until all the blocks have completed.)






share|improve this answer


























  • Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

    – Gustavo Picciuto
    Dec 29 '18 at 19:17











  • What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

    – Rob Napier
    Dec 29 '18 at 21:24













  • I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

    – Gustavo Picciuto
    Dec 29 '18 at 23:54



















0














If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.



You can plug this into a playground and mess around with it:



import UIKit
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

func firstFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i, Thread.current)
}
completion()
}

func secondFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i + 100, Thread.current)
}
completion()
}

func doWorkFunctions() {

let serialQueue = DispatchQueue(label: "serial")
//let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result

serialQueue.async {
firstFunction(completion: {
print("first function done")
})
secondFunction(completion: {
print("second function done")
})
}

}

doWorkFunctions()


Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.



Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770






share|improve this answer
























  • Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

    – Gustavo Picciuto
    Dec 30 '18 at 2:44











  • Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

    – Gustavo Picciuto
    Dec 30 '18 at 3:23











  • It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

    – Rob Napier
    Dec 30 '18 at 16:07











  • Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

    – bsod
    Dec 30 '18 at 17:05











  • The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

    – CouchDeveloper
    Dec 31 '18 at 11:29





















0














This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.



import UIKit
func workOne(completion: @escaping ()->Void){
print(Thread.current)
for i in 1...4{
sleep(1)
print(i)
}
completion()
}
func workTwo(completion: @escaping ()->Void){
print(Thread.current)
for i in 5...8{
sleep(1)
print(i)
}
completion()
}
func doWork(){
let dispatchGroup = DispatchGroup()

dispatchGroup.enter()
workOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
workTwo {
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
print(Thread.current)
print("completed!")
}
}
DispatchQueue.global(qos: .default).async {
doWork()
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53972081%2fhow-do-i-use-dispatchgroup-in-background-thread%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:



    @objc func doWorkFunctions() {
    DispatchQueue.global(qos: .background).async {
    self.firstFunction {
    self.secondFunction {
    DispatchQueue.main.async {
    print("All tasks completed")
    }
    }
    }
    }


    But assuming you have a good reason for a group here, what you need to do is to use .notify to synchronize them. .notify says "when the group is empty, submit this block to this queue."



    @objc func doWorkFunctions(){
    let queue = DispatchQueue.global(qos: .background)

    taskGroup.enter()
    queue.async {
    self.firstFunction {
    self.taskGroup.leave()
    }
    }

    taskGroup.notify(queue: queue) {
    self.taskGroup.enter()

    self.secondFunction {
    self.taskGroup.leave()
    }

    self.taskGroup.notify(queue: .main) {
    print("All tasks completed")
    }
    }
    }


    (You probably don't need taskGroup to be an instance property here. You could make it a local variable and have fewer self. references required. Each block has a reference to the group, so it will live until all the blocks have completed.)






    share|improve this answer


























    • Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

      – Gustavo Picciuto
      Dec 29 '18 at 19:17











    • What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

      – Rob Napier
      Dec 29 '18 at 21:24













    • I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

      – Gustavo Picciuto
      Dec 29 '18 at 23:54
















    1














    Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:



    @objc func doWorkFunctions() {
    DispatchQueue.global(qos: .background).async {
    self.firstFunction {
    self.secondFunction {
    DispatchQueue.main.async {
    print("All tasks completed")
    }
    }
    }
    }


    But assuming you have a good reason for a group here, what you need to do is to use .notify to synchronize them. .notify says "when the group is empty, submit this block to this queue."



    @objc func doWorkFunctions(){
    let queue = DispatchQueue.global(qos: .background)

    taskGroup.enter()
    queue.async {
    self.firstFunction {
    self.taskGroup.leave()
    }
    }

    taskGroup.notify(queue: queue) {
    self.taskGroup.enter()

    self.secondFunction {
    self.taskGroup.leave()
    }

    self.taskGroup.notify(queue: .main) {
    print("All tasks completed")
    }
    }
    }


    (You probably don't need taskGroup to be an instance property here. You could make it a local variable and have fewer self. references required. Each block has a reference to the group, so it will live until all the blocks have completed.)






    share|improve this answer


























    • Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

      – Gustavo Picciuto
      Dec 29 '18 at 19:17











    • What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

      – Rob Napier
      Dec 29 '18 at 21:24













    • I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

      – Gustavo Picciuto
      Dec 29 '18 at 23:54














    1












    1








    1







    Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:



    @objc func doWorkFunctions() {
    DispatchQueue.global(qos: .background).async {
    self.firstFunction {
    self.secondFunction {
    DispatchQueue.main.async {
    print("All tasks completed")
    }
    }
    }
    }


    But assuming you have a good reason for a group here, what you need to do is to use .notify to synchronize them. .notify says "when the group is empty, submit this block to this queue."



    @objc func doWorkFunctions(){
    let queue = DispatchQueue.global(qos: .background)

    taskGroup.enter()
    queue.async {
    self.firstFunction {
    self.taskGroup.leave()
    }
    }

    taskGroup.notify(queue: queue) {
    self.taskGroup.enter()

    self.secondFunction {
    self.taskGroup.leave()
    }

    self.taskGroup.notify(queue: .main) {
    print("All tasks completed")
    }
    }
    }


    (You probably don't need taskGroup to be an instance property here. You could make it a local variable and have fewer self. references required. Each block has a reference to the group, so it will live until all the blocks have completed.)






    share|improve this answer















    Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:



    @objc func doWorkFunctions() {
    DispatchQueue.global(qos: .background).async {
    self.firstFunction {
    self.secondFunction {
    DispatchQueue.main.async {
    print("All tasks completed")
    }
    }
    }
    }


    But assuming you have a good reason for a group here, what you need to do is to use .notify to synchronize them. .notify says "when the group is empty, submit this block to this queue."



    @objc func doWorkFunctions(){
    let queue = DispatchQueue.global(qos: .background)

    taskGroup.enter()
    queue.async {
    self.firstFunction {
    self.taskGroup.leave()
    }
    }

    taskGroup.notify(queue: queue) {
    self.taskGroup.enter()

    self.secondFunction {
    self.taskGroup.leave()
    }

    self.taskGroup.notify(queue: .main) {
    print("All tasks completed")
    }
    }
    }


    (You probably don't need taskGroup to be an instance property here. You could make it a local variable and have fewer self. references required. Each block has a reference to the group, so it will live until all the blocks have completed.)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 29 '18 at 18:43

























    answered Dec 29 '18 at 18:37









    Rob NapierRob Napier

    200k28296422




    200k28296422













    • Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

      – Gustavo Picciuto
      Dec 29 '18 at 19:17











    • What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

      – Rob Napier
      Dec 29 '18 at 21:24













    • I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

      – Gustavo Picciuto
      Dec 29 '18 at 23:54



















    • Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

      – Gustavo Picciuto
      Dec 29 '18 at 19:17











    • What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

      – Rob Napier
      Dec 29 '18 at 21:24













    • I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

      – Gustavo Picciuto
      Dec 29 '18 at 23:54

















    Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

    – Gustavo Picciuto
    Dec 29 '18 at 19:17





    Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.

    – Gustavo Picciuto
    Dec 29 '18 at 19:17













    What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

    – Rob Napier
    Dec 29 '18 at 21:24







    What exception? (Did you remember the first .enter() call at line 4? That's the most likely mistake.)

    – Rob Napier
    Dec 29 '18 at 21:24















    I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

    – Gustavo Picciuto
    Dec 29 '18 at 23:54





    I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.

    – Gustavo Picciuto
    Dec 29 '18 at 23:54













    0














    If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.



    You can plug this into a playground and mess around with it:



    import UIKit
    import PlaygroundSupport

    PlaygroundPage.current.needsIndefiniteExecution = true

    func firstFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i, Thread.current)
    }
    completion()
    }

    func secondFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i + 100, Thread.current)
    }
    completion()
    }

    func doWorkFunctions() {

    let serialQueue = DispatchQueue(label: "serial")
    //let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result

    serialQueue.async {
    firstFunction(completion: {
    print("first function done")
    })
    secondFunction(completion: {
    print("second function done")
    })
    }

    }

    doWorkFunctions()


    Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.



    Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770






    share|improve this answer
























    • Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

      – Gustavo Picciuto
      Dec 30 '18 at 2:44











    • Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

      – Gustavo Picciuto
      Dec 30 '18 at 3:23











    • It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

      – Rob Napier
      Dec 30 '18 at 16:07











    • Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

      – bsod
      Dec 30 '18 at 17:05











    • The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

      – CouchDeveloper
      Dec 31 '18 at 11:29


















    0














    If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.



    You can plug this into a playground and mess around with it:



    import UIKit
    import PlaygroundSupport

    PlaygroundPage.current.needsIndefiniteExecution = true

    func firstFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i, Thread.current)
    }
    completion()
    }

    func secondFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i + 100, Thread.current)
    }
    completion()
    }

    func doWorkFunctions() {

    let serialQueue = DispatchQueue(label: "serial")
    //let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result

    serialQueue.async {
    firstFunction(completion: {
    print("first function done")
    })
    secondFunction(completion: {
    print("second function done")
    })
    }

    }

    doWorkFunctions()


    Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.



    Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770






    share|improve this answer
























    • Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

      – Gustavo Picciuto
      Dec 30 '18 at 2:44











    • Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

      – Gustavo Picciuto
      Dec 30 '18 at 3:23











    • It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

      – Rob Napier
      Dec 30 '18 at 16:07











    • Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

      – bsod
      Dec 30 '18 at 17:05











    • The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

      – CouchDeveloper
      Dec 31 '18 at 11:29
















    0












    0








    0







    If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.



    You can plug this into a playground and mess around with it:



    import UIKit
    import PlaygroundSupport

    PlaygroundPage.current.needsIndefiniteExecution = true

    func firstFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i, Thread.current)
    }
    completion()
    }

    func secondFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i + 100, Thread.current)
    }
    completion()
    }

    func doWorkFunctions() {

    let serialQueue = DispatchQueue(label: "serial")
    //let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result

    serialQueue.async {
    firstFunction(completion: {
    print("first function done")
    })
    secondFunction(completion: {
    print("second function done")
    })
    }

    }

    doWorkFunctions()


    Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.



    Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770






    share|improve this answer













    If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.



    You can plug this into a playground and mess around with it:



    import UIKit
    import PlaygroundSupport

    PlaygroundPage.current.needsIndefiniteExecution = true

    func firstFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i, Thread.current)
    }
    completion()
    }

    func secondFunction(completion: @escaping() -> Void) {
    for i in 1...5 {
    sleep(1)
    print(i + 100, Thread.current)
    }
    completion()
    }

    func doWorkFunctions() {

    let serialQueue = DispatchQueue(label: "serial")
    //let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result

    serialQueue.async {
    firstFunction(completion: {
    print("first function done")
    })
    secondFunction(completion: {
    print("second function done")
    })
    }

    }

    doWorkFunctions()


    Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.



    Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Dec 29 '18 at 19:01









    bsodbsod

    2,1561820




    2,1561820













    • Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

      – Gustavo Picciuto
      Dec 30 '18 at 2:44











    • Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

      – Gustavo Picciuto
      Dec 30 '18 at 3:23











    • It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

      – Rob Napier
      Dec 30 '18 at 16:07











    • Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

      – bsod
      Dec 30 '18 at 17:05











    • The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

      – CouchDeveloper
      Dec 31 '18 at 11:29





















    • Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

      – Gustavo Picciuto
      Dec 30 '18 at 2:44











    • Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

      – Gustavo Picciuto
      Dec 30 '18 at 3:23











    • It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

      – Rob Napier
      Dec 30 '18 at 16:07











    • Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

      – bsod
      Dec 30 '18 at 17:05











    • The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

      – CouchDeveloper
      Dec 31 '18 at 11:29



















    Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

    – Gustavo Picciuto
    Dec 30 '18 at 2:44





    Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.

    – Gustavo Picciuto
    Dec 30 '18 at 2:44













    Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

    – Gustavo Picciuto
    Dec 30 '18 at 3:23





    Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.

    – Gustavo Picciuto
    Dec 30 '18 at 3:23













    It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

    – Rob Napier
    Dec 30 '18 at 16:07





    It's surprising that this would work in live code. This example runs completion synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction and secondFunction in a DispatchQueue.async call on a queue you don't control, in which case secondFunction will start before firstFunction finishes.

    – Rob Napier
    Dec 30 '18 at 16:07













    Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

    – bsod
    Dec 30 '18 at 17:05





    Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.

    – bsod
    Dec 30 '18 at 17:05













    The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

    – CouchDeveloper
    Dec 31 '18 at 11:29







    The common misconception here seems to be, that function firstFunction and function secondFunction ought to be asynchronous, which the @escaping modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.

    – CouchDeveloper
    Dec 31 '18 at 11:29













    0














    This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.



    import UIKit
    func workOne(completion: @escaping ()->Void){
    print(Thread.current)
    for i in 1...4{
    sleep(1)
    print(i)
    }
    completion()
    }
    func workTwo(completion: @escaping ()->Void){
    print(Thread.current)
    for i in 5...8{
    sleep(1)
    print(i)
    }
    completion()
    }
    func doWork(){
    let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()
    workOne {
    dispatchGroup.leave()
    }
    dispatchGroup.enter()
    workTwo {
    dispatchGroup.leave()
    }
    dispatchGroup.notify(queue: .main) {
    print(Thread.current)
    print("completed!")
    }
    }
    DispatchQueue.global(qos: .default).async {
    doWork()
    }





    share|improve this answer




























      0














      This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.



      import UIKit
      func workOne(completion: @escaping ()->Void){
      print(Thread.current)
      for i in 1...4{
      sleep(1)
      print(i)
      }
      completion()
      }
      func workTwo(completion: @escaping ()->Void){
      print(Thread.current)
      for i in 5...8{
      sleep(1)
      print(i)
      }
      completion()
      }
      func doWork(){
      let dispatchGroup = DispatchGroup()

      dispatchGroup.enter()
      workOne {
      dispatchGroup.leave()
      }
      dispatchGroup.enter()
      workTwo {
      dispatchGroup.leave()
      }
      dispatchGroup.notify(queue: .main) {
      print(Thread.current)
      print("completed!")
      }
      }
      DispatchQueue.global(qos: .default).async {
      doWork()
      }





      share|improve this answer


























        0












        0








        0







        This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.



        import UIKit
        func workOne(completion: @escaping ()->Void){
        print(Thread.current)
        for i in 1...4{
        sleep(1)
        print(i)
        }
        completion()
        }
        func workTwo(completion: @escaping ()->Void){
        print(Thread.current)
        for i in 5...8{
        sleep(1)
        print(i)
        }
        completion()
        }
        func doWork(){
        let dispatchGroup = DispatchGroup()

        dispatchGroup.enter()
        workOne {
        dispatchGroup.leave()
        }
        dispatchGroup.enter()
        workTwo {
        dispatchGroup.leave()
        }
        dispatchGroup.notify(queue: .main) {
        print(Thread.current)
        print("completed!")
        }
        }
        DispatchQueue.global(qos: .default).async {
        doWork()
        }





        share|improve this answer













        This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.



        import UIKit
        func workOne(completion: @escaping ()->Void){
        print(Thread.current)
        for i in 1...4{
        sleep(1)
        print(i)
        }
        completion()
        }
        func workTwo(completion: @escaping ()->Void){
        print(Thread.current)
        for i in 5...8{
        sleep(1)
        print(i)
        }
        completion()
        }
        func doWork(){
        let dispatchGroup = DispatchGroup()

        dispatchGroup.enter()
        workOne {
        dispatchGroup.leave()
        }
        dispatchGroup.enter()
        workTwo {
        dispatchGroup.leave()
        }
        dispatchGroup.notify(queue: .main) {
        print(Thread.current)
        print("completed!")
        }
        }
        DispatchQueue.global(qos: .default).async {
        doWork()
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 30 '18 at 3:58









        Gustavo PicciutoGustavo Picciuto

        86




        86






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53972081%2fhow-do-i-use-dispatchgroup-in-background-thread%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Monofisismo

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas