Multithreading in iOS-Part 3/4

NSOperation, advantage of NSOperation, operation

Manasa M P
Geek Culture
8 min readJun 1, 2021

--

If want to know about what is thread, multi thread and how gcd works please refer my first blog here.

NSOperation queue:-

Another way to create thread is using operation. After you have created instances of your operations, submit the operations to OperationQueue. The OperationQueue will manage the threads and also responsible for running the operations that you have provided to it.

What is operation? An abstract class that represents the code and data associated with a single task.

Operation States:- Operation object maintain states internally to determine when it is safe to execute and also to notify external clients of the progress through the operation’s life cycle.

Bellow are the operation states

  1. isReady: It informs client when an operation is ready to execute. This returns true when the operation is ready to execute now or false if there are still unfinished operations on which it is dependent.
  • isExecuting: This tells us whether the operation is executing the assigned task. isExecuting returns true if the operation is working on its task or false if it is not.
  • isFinished: It informs that an operation finished its task successfully or was cancelled. Operation queue does not dequeue an operation or operation object will not clear until the isFinished value changes to true.
  • isCancelled: This inform clients that the cancellation of an operation was requested.

How can you cancel operation?

We can cancel operation using cancel() as follows. We can check whether the operation is cancelled or not by isCancelled

Effect of cancel()

  • Your operation is already finished. In that case, the cancel method has no effect.
  • Your operation is already being executing. In that case, system will NOT force your operation code to stop but instead, cancelled property will be set to true.
  • Your operation is still in the queue waiting to be executed. In that case, your operation will not be executed.

How can we create operation?

Developer no need to use this directly. Foundation provides two system-defined sub classes InvocationOperation and BlockOperation to execute task.

There are mainly three ways to create operations:-

  1. BlockOperation
  2. InvocationOperation
  3. Custom Operations

BlockOperation :-

An operation that manages the concurrent execution of one or more blocks.

BlockOperation class extends from Operation class. You can use this object to execute several blocks at once without having to create separate operation objects for each. When executing more than one block, the operation itself is considered finished only when all blocks have finished executing.

Making use of the system-defined BlockOperation looks as follows:

Here block operations added into operation queue. Operation queue started that operation on some background thread and execute it.

And can also be done by adding the block directly on the queue:

How can we execute one or more block concurrently?

we can use BlockOperation to execute one or more block at once without creating new operation as follows

as you can see the tasks/blocks added to the Block operation itself executed concurrently but the block run synchronous manner means it blocked the thread at which start is called in our case it is main thread.

We can unblock main thread by calling start() method in any other thread but this will block that thread where start() method is called.

InvocationOperation:-

In objective C we can create NSInvocationOperation while it’s not available in Swift.

Custom Operations:-

Subclassing Operation gives you complete control over the implementation of your own operations which includes the ability to alter the default way in which your operation executes and reports its status.

This will block the main thread bcz here we are calling start() in main thread

creating custom concurrent operation as follows:-

call cancel() method on custom operation:

Operation Queues:-

Operations Queues are Cocoa’s high-level abstraction on GCD. Instead of starting operation by yourself, you give to operation queue. It then handle the scheduling and execution.

An operation queue executes its queued Operation objects based on their priority and in FIFO order.

An operation queue executes its operations either directly, by running them on secondary threads, or indirectly using the libdispatch library (i.e. Grand Central Dispatch)

You can add as many operations as you want, but they don’t all get executed at the same time. Instead, OperationQueue limits the number of operations based on system conditions

we can cancel operation queue as

Operation queues retain operations until they’re finished. Suspending an operation queue with operations that aren’t finished can result in a memory leak.

How can we set maximum Concurrent Operation on operation queue?

maxConcurrentOperationCount help us to set max concurrent operation but it’s recommended not to set.

The maxConcurrentOperationCount is set to 1 to allow operations finishing one by one. it act as serial queue

by default value is -1 which means let the system decide

How does the queue decide how many operations it can run at once?

It depends on the hardware. By default, OperationQueue does some calculation behind the scenes and decides the maximum possible number of threads depending on platform it’s running on.

In which order operation queue executes task?

Operations within a queue are organised according to their readiness i.e. (isReady property returns true), priority level & dependencies, and are executed accordingly.

If all of the queued operations have the same queuePriority and are ready to execute when they are put in the queue, they’re executed in the order in which they were submitted to the queue. Otherwise, the operation queue always executes the one with the highest priority relative to the other ready operations.

An operation object will not be ready to execute until all of its dependent operations have finished executing.

Adding operation to operation queue and set maxConcurrentOperationCount

How to add dependency between operation?

Consider a situation where you need to call two api after these api completion you need to parse a response then you need to use dependency manager to achieve this

without dependency between operation

with dependency between operation

Dispatch Group Implementation Using Operations Queue:-

we used GCD dispatch group feature to block a thread until one or more tasks finished executing.

we implemented the same behaviour using Operation Queues by using dependencies. This is useful when you can’t do anything until all of the specified tasks are completed.

In some situation you need to run concurrently and when all the tasks finished we need to call some method to indicate that all tasks has finished. this can be achieve by using waitUntilFinished

Asynchronous Versus Synchronous Operations:-

If you plan on executing an operation object manually, instead of adding it to a queue, you can design your operation to execute in a synchronous or asynchronous manner.

Operation objects are synchronous by default. When you call the start() method of a synchronous operation directly from your code, the operation executes immediately in the current thread.

When you call the start() method of an asynchronous operation, that method may return before the corresponding task is completed. An asynchronous operation object is responsible for scheduling its task on a separate thread.

Benefits of Operation Queues Over GCD:-

  1. Operation queues are high-level abstraction of the queue model and is made on top of GCD.
  2. The Operation API provides support for dependencies. You can create complex dependencies between tasks very easily though in GCD you can achieve it but you have to do a lot of work.
  3. The NSOperation and NSOperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing).
  4. You can monitor the state of an operation or operation queue.
  5. Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. It gives control over operation life cycle
  6. you can specify the maximum number of queued operations that can run simultaneously. This makes it easy to control how many operations run at the same time or to create a serial operation queue.

7. Unlike GCD, they don’t conform to the First-In-First-Out order.

Note:

Enjoy your coding. I hope you learnt something from this blog. Please hit the clap button below 👏 to help others find it!. follow me on Medium.

--

--