0

I am trying to call a method that when called, executes in the background of the global thread of my app. If I call it once, it works fine. If I call the method multiple times, I get weird outputs as the tasks from the previous method calls are still running in the background.

    previousWorkItem?.cancel()
    

    let workItem = DispatchWorkItem {let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
        let dbRef = Database.database().reference().child("shows").child(listingID).child("selectedListing")
        var count = 0
        
        let components = start_time.components(separatedBy: ":")
        let minutes = Int(components[0]) ?? 0
        let seconds = Int(components[1]) ?? 0
        let totalSeconds = minutes * 60 + seconds
        let newMinutes = totalSeconds / 60
        var newSeconds = totalSeconds % 60
        
        if viewer_side {
            newSeconds += 5
        }
        
        print(newSeconds)
        while newSeconds >= 0 {
            sleep(1)
            if newSeconds < 10 {
                dbRef.updateChildValues(["timer": "0\(newMinutes):0\(newSeconds)"]) { error, ref in
                    if let error = error {
                        print("Error updating timer: \(error.localizedDescription)")
                    }
                }
            } else {
                dbRef.updateChildValues(["timer": "0\(newMinutes):\(newSeconds)"]) { error, ref in
                    if let error = error {
                        print("Error updating timer: \(error.localizedDescription)")
                    }
                }
            }
            
            newSeconds -= 1
        }}
    
    
    DispatchQueue.global(qos: .background).async(execute: workItem)
    previousWorkItem = workItem
`

Is there some way I can cancel all the previous processes in the Queue before executing the contents of the method called?

I tried assigning the contents inside the queue to DispatchWorkItem and then cancelling the previous assigned one every time a method was run but, wasn't able to execute the DispatchWorkItem.

aali
  • 1
  • 2

1 Answers1

0

Over DispatchQueue the task management can be done by using the DispatchWorkItem like this

import Foundation

var workItem: DispatchWorkItem? = nil

func executeSomeTask(name: String) {
    if workItem != nil {
        workItem?.cancel()
    }
     workItem = DispatchWorkItem {
        // Your task code here
        sleep(10)
        print("Executed the task \(name)")
    }

    workItem?.notify(queue: DispatchQueue.global()) {
        // Cancellation handler code here
        print("Cancelled the task \(name)")
    }
    DispatchQueue.global().async(execute: workItem!)
}

executeSomeTask(name: "1")
executeSomeTask(name: "2")

Out Put:

Cancelled the task 1
Executed the task 2
Cancelled the task 2
vignesh
  • 994
  • 10
  • 12
  • from what I see, this cancels after the work item is executed. What i'm trying to do is cancel any previous processes before starting a new DispatchWorkItem. So still not fixed unfortunately – aali Apr 27 '23 at 10:27
  • the cancel() does get executed, but the previous background task still runs. I've added the contents of my DispatchWorkItem if that helps. – aali Apr 27 '23 at 10:48
  • Can you explain why the timer has been created inside the task? If the db operation is done periodically then the timer can be moved out which creates the `DispatchWorkItem` and executes the task on background. – vignesh Apr 27 '23 at 10:56
  • no particular reason why, have tried keeping inside the `DispatchWorkItem` just the writing into the db operation but still the same because the contents inside the `DispatchWorkItem` still get executed after using `cancel()` – aali Apr 27 '23 at 12:45