Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSOperation and NSOperationQueue working thread vs main thread

I have to carry out a series of download and database write operations in my app. I am using the NSOperation and NSOperationQueue for the same.

This is application scenario:

  • Fetch all postcodes from a place.
  • For each postcode fetch all houses.
  • For each house fetch inhabitant details

As said, I have defined an NSOperation for each task. In first case (Task1), I am sending a request to server to fetch all postcodes. The delegate within the NSOperation will receive the data. This data is then written to database. The database operation is defined in a different class. From NSOperation class I am making a call to the write function defined in database class.

My question is whether the database write operation occur in main thread or in a background thread? As I was calling it within a NSOperation I was expecting it to run in a different thread (Not MainThread) as the NSOperation. Can someone please explain this scenario while dealing with NSOperation and NSOperationQueue.

like image 271
Zach Avatar asked Oct 24 '13 14:10

Zach


People also ask

What is the difference between NSOperationQueue and GCD?

GCD is a low-level C-based API that enables very simple use of a task-based concurrency model. NSOperation and NSOperationQueue are Objective-C classes that do a similar thing. NSOperation was introduced first, but as of 10.5 and iOS 2, NSOperationQueue and friends are internally implemented using GCD .

Which is the best of GCD Nsthread or NSOperationQueue?

There is no generic "best" out of the three.

What is main thread in iOS?

The main thread is the one that starts our program, and it's also the one where all our UI work must happen. However, there is also a main queue, and although sometimes we use the terms “main thread” and “main queue” interchangeably, they aren't quite the same thing.

How many types of threads are there in Swift?

As I understand there are 3 types of DispatchQueue in swift: Main (serial) (Main Thread) Global (Concurrent) (Background Threads working in parallel) Custom (Concurrent or serial)


2 Answers

My question is whether the database write operation occur in main thread or in a background thread?

If you create an NSOperationQueue from scratch as in:

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; 

It will be in a background thread:

Operation queues usually provide the threads used to run their operations. In OS X v10.6 and later, operation queues use the libdispatch library (also known as Grand Central Dispatch) to initiate the execution of their operations. As a result, operations are always executed on a separate thread, regardless of whether they are designated as concurrent or non-concurrent operations

Unless you are using the mainQueue:

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; 

You can also see code like this:

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; [myQueue addOperationWithBlock:^{     // Background work      [[NSOperationQueue mainQueue] addOperationWithBlock:^{         // Main thread work (UI usually)     }]; }]; 

And the GCD version:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)              {               // Background work                          dispatch_async(dispatch_get_main_queue(), ^(void)               {                    // Main thread work (UI usually)                                         }); }); 

NSOperationQueue gives finer control with what you want to do. You can create dependencies between the two operations (download and save to database). To pass the data between one block and the other, you can assume for example, that a NSData will be coming from the server so:

__block NSData *dataFromServer = nil; NSBlockOperation *downloadOperation = [[NSBlockOperation alloc] init]; __weak NSBlockOperation *weakDownloadOperation = downloadOperation;  [weakDownloadOperation addExecutionBlock:^{  // Download your stuff    // Finally put it on the right place:   dataFromServer = ....  }];  NSBlockOperation *saveToDataBaseOperation = [[NSBlockOperation alloc] init]; __weak NSBlockOperation *weakSaveToDataBaseOperation = saveToDataBaseOperation;   [weakSaveToDataBaseOperation addExecutionBlock:^{  // Work with your NSData instance  // Save your stuff  }];  [saveToDataBaseOperation addDependency:downloadOperation];  [myQueue addOperation:saveToDataBaseOperation]; [myQueue addOperation:downloadOperation]; 

Edit: Why I am using __weak reference for the Operations, can be found here. But in a nutshell is to avoid retain cycles.

like image 196
Rui Peres Avatar answered Sep 22 '22 21:09

Rui Peres


If you want to perform the database writing operation in the background thread you need to create a NSManagedObjectContext for that thread.

You can create the background NSManagedObjectContext in the start method of your relevant NSOperation subclass.

Check the Apple docs for Concurrency with Core Data.

You can also create an NSManagedObjectContext that executes requests in its own background thread by creating it with NSPrivateQueueConcurrencyType and performing the requests inside its performBlock: method.

like image 40
serrrgi Avatar answered Sep 19 '22 21:09

serrrgi