How can I Pause a NSOperation in a NSOperationQueue?
Asked Answered
J

3

19

I need to pause a running NSOperation which was inserted in an NSOperationQueue. Currently I am canceling all operations and restarting them. But this would lead to some kind of duplication in terms of process done. I tried with setSuspended flag of NSOperationQueue. But it's not suspending the operation. Is there any way out?

Jessabell answered 16/8, 2012 at 8:50 Comment(0)
V
14

see this: Link

And here from the apple docs:

Suspending and Resuming Queues If you want to issue a temporary halt to the execution of operations, you can suspend the corresponding operation queue using the setSuspended: method.

Suspending a queue does not cause already executing operations to pause in the middle of their tasks. It simply prevents new operations from being scheduled for execution. You might suspend a queue in response to a user request to pause any ongoing work, because the expectation is that the user might eventually want to resume that work.

Volkan answered 16/8, 2012 at 9:6 Comment(2)
Thanks! I tried to implement as from your link. I added a new variable called 'isPaused' inside the NSOperation and whenever I need to pause the operation, I will set it's value to YES. Inside NSOperation I will regularly check the value of 'isPaused'. Whenever I find it to 'YES' I will break out of the loop. But I have serious problem here. I am trying to set the value of 'isPaused' from main thread. This may lead to some race conditions. Is there any way to get rid of the race conditions? Is there any way to call the methods (to pause and resume) in the same thread (rather than main thread)?Jessabell
@Advaith: If both threads lock a mutex before reading from or writing to 'isPaused', you won't have to worry about races.Neglectful
G
3

I've not tried this, but I would probably start here:

  • add a isPaused flag to your NSOperation subclass
  • implement a copy/move method for the operation's data
  • if paused, setCancelled: (watch for this change in -main)
  • create a new operation moving the state from paused operation to new operation
  • adjust priority to reorder operation order in queue, if you like
  • add the clone to the queue
  • return from -main if in -main

note that this will just suspend it. if you really want to pause and explicitly resume, you would manually 'new operation` when you want to resume.

now, if you are observing or have special completions, then you will have a few other problems. for simple cases, it seems this approach would seem to work fine.

Gardal answered 16/8, 2012 at 10:3 Comment(0)
O
2

In Swift 5, you can use isSuspended property to pause and resume your OperationQueue, you can see the example for more understanding:-

let operationQueue = OperationQueue()

let op1 = BlockOperation {
    print("done")
}
let op2 = BlockOperation {
    print("op2")
}
let op3 = BlockOperation {
    print("op3")
}

op1.addDependency(op2)
operationQueue.addOperations([op1, op2, op3], waitUntilFinished: false)

operationQueue.isSuspended = true
print("operationQueue suspended")

if operationQueue.isSuspended {
    operationQueue.isSuspended = false
    print("operationQueue restarted")
}


OutPut:- 
op2
op3
operationQueue suspended
operationQueue restarted
done
Ornithopter answered 16/7, 2020 at 7:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.