Search code examples
iosswiftnsoperationqueue

Swift -Start/Stop Synchronous OperationQueue


I have some operations that need to run synchronously. I tried to follow this link but it's not clear enough for my situation.

op2 doesn't start until op1 is finished and op3 doesn't start until op2 is finished but during that time I need to be able to stop any of the operations and restart all over again. For example if op2 is running, I know that it cannot be stopped, but for whatever reason I need to be able to prevent op3 from executing because op1 has restarted. How can I do this?

This is a very simple example, the actual code is more intricate

var queue1 = OperationQueue()
var queue2 = OperationQueue()
var queue3 = OperationQueue()
     
var operation1: BlockOperation?
var operation2: BlockOperation?
var operation3: BlockOperation?

// a DispatchGroup has finished running now it's time to start the operations ...
dispatchGroup.notify(queue: .global(qos: .background)) { [weak self] in
    DispatchQueue.main.async { [weak self] in

        self?.runFirstFunc()
    }
}

func runFirstFunc() {

   var count = 0

   let num in arr  {
       count += num
   }

   // now that the loop is finished start the second func but there is a possibility something may happen in the first that should prevent the second func from running
   runSecondFunc(count: count)
}

func runSecondFunc(count: Int) {

    do {

        try ...

        // if the do-try is successful do something with count then start thirdFunc but there is a possibility something may happen in the second func that should prevent the third func from running
        runThirdFunc()

    } catch {
        return
    }
}

func runThirdFunc() {

    // this is the final operation, once it hits here I know it can't be stopped even if I have to restart op1 again but that is fine
}

Solution

  • You said:

    op2 doesn't start until op1 is finished and op3 doesn't start until op2 is finished ...

    If using OperationQueue you can accomplish that by creating the three operations, and defining op1 to be a dependency of op2 and defining op2 as a dependency of op3.

    ... but during that time I need to be able to stop any of the operations and restart all over again.

    If using OperationQueue, if you want to stop all operations that have been added to the queue, you call cancelAllOperations.

    For example if op2 is running, I know that it cannot be stopped, ...

    Well, it depends upon what op2 is doing. If it's spinning in a loop doing calculations, then, yes, it can be canceled, mid-operation. You just check isCancelled, and if it is, stop the operation in question. Or if it is a network request (or something else that is cancelable), you can override cancel method and cancel the task, too. It depends upon what the operation is doing.

    ... but for whatever reason I need to be able to prevent op3 from executing because op1 has restarted.

    Sure, having canceled all the operations with cancelAllOperations, you can then re-add three new operations (with their associated dependencies) to the queue.