Monday, July 29, 2013

Concurrency in iOS

First of all, let's understand some basic concept:
Main queue
This queue performs all its tasks on the main thread, which is where Cocoa and Cocoa Touch require programmers to call all UI-related methods. Use the dispatch_get_main_queue function to retrieve the handle on the main queue.

Concurrent queues
These are queues that you can retrieve from GCD in order to execute asynchronous or synchronous tasks. Use the dispatch_get_global_queue function to retrieve the handle to a concurrent queue.

Serial queues
These are queues that, no matter whether you submit synchronous or asynchronous tasks to them, will always execute their tasks in the first-in-first-out(FIFO) fashion. Use the dispatch_queue_create to create a serial queue. Once you are done with the queue, you must release it using dispath_release function.

Only one main queue, but you can create as many serial dispatch queues as you want. Tasks can be handed to dispatch queues in two forms: block objects or C functions.

Main subjects to handle concurrency, Grand Central Dispatch, Threads,Timers,Operation and Operation Queues.


Grand Central Dispatch
Performing UI-Related Tasks with GCD

use dispatch_get_main_queue, UI-related tasks have to be performed on the main thread.
Code Snippet,

       dispatch_queue_t mainQueue = dispatch_get_main_queue(); 

       dispatch_async(mainQueue, ^(void) {
       [[[UIAlertView alloc] initWithTitle:@"GCD" message:@"GCD is amazing!"
           delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show]; 
       });

Executing Non-UI Related Tasks Synchronously with GCD
use the dispatch_sync function



              void (^printFrom1To1000)(void) = ^{
              NSUInteger counter = 0; for (counter = 1;
              counter <= 1000; counter++){
              NSLog(@"Counter = %lu - Thread = %@", (unsigned long)counter,
              [NSThread currentThread]);
              } }; 


dispatch_queue_t concurrentQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

           dispatch_sync(concurrentQueue, printFrom1To1000); 
           dispatch_sync(concurrentQueue, printFrom1To1000); 

The priority of the concurrent queue that GCD has to retrieve for the programmer.

DISPATCH_QUEUE_PRIORITY_LOW
Fewer timeslices will be applied to your task than normal tasks.

DISPATCH_QUEUE_PRIORITY_DEFAULT
The default system priority for the code execution will be applied to your task.

DISPATCH_QUEUE_PRIORITY_HIGH
More timeslices will be applied to your task than normal tasks.

Executing Non-UI Related Tasks Asychronously with GCD
Use dispatch_async


          dispatch_queue_t concurrentQueue =              dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        dispatch_async(concurrentQueue, ^{
              __block UIImage *image = nil;
             dispatch_sync(concurrentQueue, ^{ /* Download the image here */
             });
        dispatch_sync(dispatch_get_main_queue(), ^{

      /* Show the image to the user here on the main queue*/

        }); }); 


Performing Tasks After a Delay with GCD
use the dispatch_after and dispatch_after_f functions


             double delayInSeconds = 2.0;
             dispatch_time_t delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

             dispatch_queue_t concurrentQueue =          dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 


             dispatch_after(delayInNanoSeconds, concurrentQueue, ^(void){ /* Perform your operations here */
}); 

Performing a Task Only Once with GCD
use the dispatch_once function


No comments:

Post a Comment