5

I need to run several functions and the order in which the functions are executed is very important. I have two non-async functions that need to be run and then two async functions that need to be executed after that. All of the functions must be executed upon the completion of the previous function.

So far I have the following. However, the async functions do not seem to follow the dependencies that I have laid out. Both async functions are executed as soon as the queue begins.

Is there something I am missing? Any help is appreciated! :)

let queue = OperationQueue()


let operation1 = BlockOperation {
    nonAsyncFunc1()
}
let operation2 = BlockOperation {
    nonAsyncFunc2()
}
let operation3 = BlockOperation {
    asyncFunc1()
}
let operation4 = BlockOperation {
    asyncFunc2()
}
                                    
operation2.addDependency(operation1)
operation3.addDependency(operation2)
operation4.addDependency(operation3)
                    
self.queue.addOperation(operation1)
self.queue.addOperation(operation2)
self.queue.addOperation(operation3)
self.queue.addOperation(operation4)
devOP1
  • 295
  • 3
  • 13
  • 1
    I notice that your OperationQueue is concurrent. You probably want it to be serial, so that no operation can even start until the preceding operation on the queue has finished. However it is not obvious to me how you think your block operation is going to _know_ when an async function has finished; I do hope your real code is a lot more sophisticated than what you've shown here. – matt Aug 24 '21 at 22:02
  • 1
    Having said that, if at all possible, I would recommend using the Combine framework for this sort of thing, not Operations. It's all so easy with Combine; serializing asynchronousness is exactly what it is for. (If you could confine yourself to iOS 15 you could, of course, use the new `async/await` stuff, which is the easiest of all.) – matt Aug 24 '21 at 22:06
  • @matt Thanks, I will have a look at serializing async functions with the Combine framework. If you would like you could add an example as an answer to this question. – devOP1 Aug 24 '21 at 22:14
  • 1
    I've said a great deal on this topic, both in my online Combine tutorial https://www.apeth.com/UnderstandingCombine/ and on Stack Overflow. I don't think another answer saying the same thing would be useful. – matt Aug 24 '21 at 22:19

1 Answers1

0

If you want to run operations serially you have to limit the maxConcurrentOperationCount of the queue to 1. This will ensure that only one operation is performed at one time.

Also, BlockOperation finishes as soon as all of the blocks have returned, for example as soon as your asyncFunc1 and asyncFunc2 function returns your BlockOperation signals completion. So if inside your async function you are calling any URLSessionTask the operation would complete before the task completes. You have to create your own async operation by inheriting Operation class and overriding isAsynchronous property and signal operation completion manually when your internal async tasks complete.

Soumya Mahunt
  • 2,148
  • 12
  • 30