Using BlockOperation

In this section, we will be using the same DoCalculation class that we used in the Grand Central Dispatch section to keep our queues busy with work so that we could see how the OpererationQueue class works.

The BlockOperation class is a concrete implementation of the Operation type that can manage the execution of one or more blocks. This class can be used to execute several tasks at once without the need to create separate operations for each task.

Let's see how we can use the BlockOperation class to add concurrency to our application. The following code shows how to add three tasks to an operation queue using a single BlockOperation instance:

let calculation = DoCalculations() 
let blockOperation1: BlockOperation = BlockOperation.init( 
  block: { 
    calculation.performCalculation(10000000, tag: "Operation 1") 
  } 
) 
blockOperation1.addExecutionBlock({ 
  calculation.performCalculation(10000, tag: "Operation 2") 
}) 
blockOperation1.addExecutionBlock({ 
  calculation.performCalculation(1000000, tag: "Operation 3") 
}) 
let operationQueue = OperationQueue() 
operationQueue.addOperation(blockOperation1) 

In this code, we begin by creating an instance of the DoCalculation class and an instance of the OperationQueue class. Next, we created an instance of the BlockOperation class using the init constructor. This constructor takes a single parameter, which is a block of code that represents one of the tasks we want to execute in the queue. Next, we add two additional tasks using the addExecutionBlock() method.

One of the differences between dispatch queues and operations is that, with dispatch queues, if resources are available, the tasks are executed as they are added to the queue. With operations, the individual tasks are not executed until the operation itself is submitted to an operation queue. This allows us to initiate all of the operations into a single block operation prior to executing them.

Once we add all the tasks to the BlockOperation instance, we then add the operation to the OperationQueue instance that we created at the beginning of the code. At this point, the individual tasks within the operation start to execute.

This example shows how to use BlockOperation to queue up multiple tasks and then pass the tasks to the operation queue. The tasks are executed in a FIFO order; therefore, the first task that is added will be the first task executed. However, the tasks can be executed concurrently if we have the available resources. The output from this code should look similar to this:

time for Operation 2:  0.00546294450759888
time for Operation 3:  0.0800899863243103
time for Operation 1:  0.484337985515594

What if we do not want the tasks to run concurrently? What if we wanted them to run serially like the serial dispatch queue? We can set a property in the operation queue that defines the number of tasks that can be run concurrently in the queue. The property is named maxConcurrentOperationCount, and is used like this:

operationQueue.maxConcurrentOperationCount = 1

However, if we add this line to our previous example, it will not work as expected. To see why this is, we need to understand what the property actually defines. If we look at Apple's OperationQueue class reference, the definition of the property is, the maximum number of queued operations that can execute at the same time.

What this tells us is that this property defines the number of operations (this is the keyword) that can be executed at the same time. The BlockOperation instance, which we added all of the tasks to, represents a single operation, therefore, no other BlockOperation added to the queue will execute until the first one is complete, but the individual tasks within the operation will execute concurrently. To run the tasks serially, we would need to create a separate instance of BlockOperation for each task.

Using an instance of the BlockOperation class is good if we have several tasks that we want to execute concurrently, but they will not start executing until we add the operation to an operation queue. Let's look at a simpler way of adding tasks to an operation queue using the addOperationWithBlock() method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset