DispatchGroup sequential execution problem
Asked Answered
R

1

-2

I am trying to implement dispath group , to perform a sequence of operations , that should execute one after another. But the issue is all the tasks adding to the group are executing in parallel. Please share your thoughts , following is the sample I am trying.

    let group = DispatchGroup()
    
    group.enter()
    print("Enter Activity One")
    self.performActivityOne(param: []) {
        group.leave()
        print("leave 1")
    }
    
    group.enter()
    print("Enter Activity two")
    self. self.performActivityTwo(param: []) {
        group.leave()
        print("leave 2")
    }
    
    group.notify(queue: DispatchQueue.main) {
        // This block will be executed once all above threads completed and call dispatch_group_leave
        print("Prepare completed. I'm readyyyy")
    }

The output I am getting is

Enter Activity One
Enter Activity two
leave 2
Repertory answered 9/8, 2022 at 14:17 Comment(10)
That’s not what dispatch groups are for. They are for knowing when a series of concurrent requests are done.Gingham
Use the same pattern as Apple suggested for Swift Concurrency TaskGroup: A dictionary with sortable keys. Before leaving the group write the value into the dictionary by the current key. In the notify closure get the keys, sort them and get the values in order.Tragic
Thanks .. do you have any reference to share?Repertory
Watch the related WWDC 2021 video.Tragic
Assuming you really want to run these two step sequentially, are you open to refactoring this code to use Swift concurrency’s async-await? That is the modern (and elegant) way to establish dependencies between asynchronous methods.Gingham
Thanks a lot for the comment , I am able to achieve this using DispatchSemaphoreRepertory
Eventhough I found the solution , can anyone please let me know the real difference between serial and concurrent queueRepertory
@Gingham I know. But if there are no data dependencies and you need to preserve the order the dictionary way is reasonable.Tragic
“can anyone please let me know the real difference between serial and concurrent queue” … I think you know the difference (that they run things sequentially and concurrently, respectively). I’m wagering that the reason you’re asking is that your serial queue attempt did not yield the desired sequential execution. It is because if you dispatch your asynchronous performActivityX calls to a serial queue, you are serializing only the starting of those asynchronous tasks, but not waiting for them to finish.Gingham
Why do you want these to run serially? If it is because you need the results in a particular order, then serial execution is completely the wrong approach altogether. You should let them execute in parallel and then gather the results in order. You only force serial execution if you actually need the results of one task in order to prepare the next task.Gingham
R
-2

Thanks for all the support and valuable comments , I fixed the issue by using Semaphores:

let semaphore = DispatchSemaphore(value: 1)
    DispatchQueue.global(qos: .userInitiated).async {
         let dispatchGroup = DispatchGroup()

         dispatchGroup.enter()
        semaphore.wait()
        self.performActivityOne(param: []) {
            dispatchGroup.leave()
            print("leave")
            semaphore.signal()
        }
        
        dispatchGroup.enter()
        semaphore.wait()
        self. self.performActivityTwo(param: []) {
            dispatchGroup.leave()
            print("leave 2")
            semaphore.signal()
        }
        
    dispatchGroup.wait()
      DispatchQueue.main.async {
         print("Completed all"))
      }
    }
Repertory answered 9/8, 2022 at 14:39 Comment(1)
In times of Swift Concurrency a semaphore is the worst choice.Tragic

© 2022 - 2024 — McMap. All rights reserved.