2

I am studying the NSOperation Object. According to the App Document (Listing 2-5), we can implement an asynchronously NSOperation. The part of the start part is as below:

- (void)start {
   // Always check for cancellation before launching the task.
   if ([self isCancelled])
   {
      // Must move the operation to the finished state if it is canceled.
      [self willChangeValueForKey:@"isFinished"];
      finished = YES;
      [self didChangeValueForKey:@"isFinished"];
      return;
   }

   // If the operation is not canceled, begin executing the task.
   [self willChangeValueForKey:@"isExecuting"];
   [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
   executing = YES;
   [self didChangeValueForKey:@"isExecuting"];
}

I find out that a new thread is assigned to run the main function:

[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];

So, it seems that the NSOperation did nothing about the concurrent execution. The asynchrony is achieve by create a new thread. So why we need NSOperation?

Michael Dorner
  • 17,587
  • 13
  • 87
  • 117
itenyh
  • 1,921
  • 2
  • 23
  • 38
  • There are many, many question: Where is the NSOperation in your code? NSOperation is a high-level abstraction for Grand Central Dispatch. Are you aware that NSOperations are asynchronous and that there is a difference between [concurrency (e.g. NSOperation) and parallelism (e.g. NSThread)](http://stackoverflow.com/a/1050257/1864294)? – Michael Dorner Oct 10 '15 at 08:37

1 Answers1

2

You may use a concurrent NSOperation to execute an asynchronous task. We should emphasize on the fact, that the asynchronous task's main work will execute on a different thread than where its start method has been invoked.

So, why is this useful?

Wrapping an asynchronous task into a concurrent NSOperation lets you leverage NSOperationQueue and furthermore enables you to setup dependencies between other operations.

For example, enqueuing operations into a NSOperationQueue lets you define how many operations will execute in parallel. You can also easily cancel the whole queue, that is, all operations which have been enqueued.

An NSOperationQueue is also useful to associate it with certain resources - for example, one queue executes CPU bound asynchronous tasks, another executes an IO bound task, and yet another executes tasks related to Core Data, and so force. For each queue you can define the maximum number of concurrent operations.

With dependencies you can achieve composition. That means for example, you can define that Operation C only executes after Operation A and B have been finished. With composition you can solve more complex asynchronous problems.

That's it, IMHO.

I would like to mention, that using NSOperations is somewhat cumbersome, clunky and verbose, which requires a lot of boilerplate code and subclasses and such. There are much better alternatives which require third party libraries, though.

CouchDeveloper
  • 18,174
  • 3
  • 45
  • 67
  • As the operation in the queue is executed in another thread, is it still necessary to call the main method in a new thread in the start method (the line '[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];'). Please have a look at the code I have posted. – itenyh Oct 15 '15 at 07:32
  • You _need_ override the `start` method in a subclass for a _concurrent_ operation. This method must schedule its work _asynchronously_. The approach you use to accomplish to schedule the main work asynchronously is irrelevant. You could use a NSThread, a dispatch queue, an asynchronous method, a CoreData `performBlock:` method or other means. You need to care about concurrency when you modify the properties of an NSOperation and subclass, and use suitable synchronisation primitives. – CouchDeveloper Oct 15 '15 at 08:01