In OS X v10.6 and later, operation queues ignore the value returned by this method and always start operations on a separate thread.
Concurrent Versus Non-Concurrent 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 concurrent or non-concurrent manner. Operation objects are non-concurrent by default. In a non-concurrent operation, the operation’s task is performed synchronously—that is, the operation object does not create a separate thread on which to run the task. Thus, when you call the start method of a non-concurrent operation directly from your code, the operation executes immediately in the current thread. By the time the start method of such an object returns control to the caller, the task itself is complete.
In contrast to a non-concurrent operation, which runs synchronously, a concurrent operation runs asynchronously. In other words, when you call the start method of a concurrent operation, that method could return before the corresponding task is completed. This might happen because the operation object created a new thread to execute the task or because the operation called an asynchronous function. It does not actually matter if the operation is ongoing when control returns to the caller, only that it could be ongoing.
If you always plan to use queues to execute your operations, it is simpler to define them as non-concurrent. If you execute operations manually, though, you might want to define your operation objects as concurrent to ensure that they always execute asynchronously. Defining a concurrent operation requires more work, because you have to monitor the ongoing state of your task and report changes in that state using KVO notifications. But defining concurrent operations can be useful in cases where you want to ensure that a manually executed operation does not block the calling thread.
For information on how to define both concurrent and non-concurrent operations, see the subclassing notes.
Note: In OS X v10.6, operation queues ignore the value returned by isConcurrent and always call the start method of your operation from a separate thread. In OS X v10.5, however, operation queues create a thread only if isConcurrent returns NO. In general, if you are always using operations with an operation queue, there is no reason to make them concurrent.
Returns a Boolean value indicating whether the operation runs asynchronously.
- (BOOL)isConcurrent
YES if the operation runs asynchronously with respect to the current thread or NO if the operation runs synchronously on whatever thread started it. This method returns NO by default.
If you are implementing a concurrent operation, you must override this method and return YES from your implementation. For more information about the differences between concurrent and non-concurrent operations, see “Concurrent Versus Non-Concurrent Operations.”
Begins the execution of the operation.
- (void)start
The default implementation of this method updates the execution state of the operation and calls the receiver’s main method. This method also performs several checks to ensure that the operation can actually run. For example, if the receiver was cancelled or is already finished, this method simply returns without calling main. (In OS X v10.5, this method throws an exception if the operation is already finished.) If the operation is currently executing or is not ready to execute, this method throws an NSInvalidArgumentException exception. In OS X v10.5, this method catches and ignores any exceptions thrown by your main method automatically. In OS X v10.6 and later, exceptions are allowed to propagate beyond this method. You should never allow exceptions to propagate out of your main method.
Note: An operation is not considered ready to execute if it is still dependent on other operations that have not yet finished. If you are implementing a concurrent operation, you must override this method and use it to initiate your operation. Your custom implementation must not call super at any time. In addition to configuring the execution environment for your task, your implementation of this method must also track the state of the operation and provide appropriate state transitions. When the operation executes and subsequently finishes its work, it should generate KVO notifications for the isExecuting and isFinished key paths respectively. For more information about manually generating KVO notifications, see Key-Value Observing Programming Guide.
You can call this method explicitly if you want to execute your operations manually. However, it is a programmer error to call this method on an operation object that is already in an operation queue or to queue the operation after calling this method. Once you add an operation object to a queue, the queue assumes all responsibility for it.
Performs the receiver’s non-concurrent task.
- (void)main
The default implementation of this method does nothing. You should override this method to perform the desired task. In your implementation, do not invoke super.
If you are implementing a concurrent operation, you are not required to override this method but may do so if you plan to call it from your custom start method.
The NSOperationQueue class regulates the execution of a set of NSOperation objects. After being added to a queue, an operation remains in that queue until it is explicitly canceled or finishes executing its task. Operations within the queue (but not yet executing) are themselves organized according to priority levels and inter-operation object dependencies and are executed accordingly. An application may create multiple operation queues and submit operations to any of them.
Inter-operation dependencies provide an absolute execution order for operations, even if those operations are located in different operation queues. An operation object is not considered ready to execute until all of its dependent operations have finished executing. For operations that are ready to execute, the operation queue always executes the one with the highest priority relative to the other ready operations. For details on how to set priority levels and dependencies, see NSOperation Class Reference.
You cannot directly remove an operation from a queue after it has been added. An operation remains in its queue until it reports that it is finished with its task. Finishing its task does not necessarily mean that the operation performed that task to completion. An operation can also be canceled. Canceling an operation object leaves the object in the queue but notifies the object that it should abort its task as quickly as possible. For currently executing operations, this means that the operation object’s work code must check the cancellation state, stop what it is doing, and mark itself as finished. For operations that are queued but not yet executing, the queue must still call the operation object’s start method so that it can processes the cancellation event and mark itself as finished.
Note: In OS X v10.6 and later, canceling an operation causes the operation to ignore any dependencies it may have. This behavior makes it possible for the queue to execute the operation’s start method as soon as possible. The start method, in turn, moves the operation to the finished state so that it can be removed from the queue. In OS X v10.5, a canceled operation does not ignore its dependencies, meaning that those dependencies must complete normally before the canceled operation can run and be removed from the queue.
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. In OS X v10.5, however, operations are executed on separate threads only if their isConcurrent method returns NO. If that method returns YES, the operation object is expected to create its own thread (or start some asynchronous operation); the queue does not provide a thread for it.
Note: In iOS 4 and later, operation queues use Grand Central Dispatch to execute operations. Prior to iOS 4, they create separate threads for non-concurrent operations and launch concurrent operations from the current thread. For a discussion of the difference between concurrent and non-concurrent operations and how they are executed, see NSOperation Class Reference.
Returns the operation queue associated with the main thread.
+ (id)mainQueue
The default operation queue bound to the main thread.
The returned queue executes operations on the main thread. The main thread’s run loop controls the execution times of these operations.
Returns the operation queue that launched the current operation.
+ (id)currentQueue
The operation queue that started the operation or nil if the queue could not be determined.
You can use this method from within a running operation object to get a reference to the operation queue that started it. Calling this method from outside the context of a running operation typically results in nil being returned.
An NSThread object controls a thread of execution. Use this class when you want to have an Objective-C method run in its own thread of execution. Threads are especially useful when you need to perform a lengthy task, but don’t want it to block the execution of the rest of the application. In particular, you can use threads to avoid blocking the main thread of the application, which handles user interface and event-related actions. Threads can also be used to divide a large job into several smaller jobs, which can lead to performance increases on multi-core computers.
Prior to OS X v10.5, the only way to start a new thread is to use the detachNewThreadSelector:toTarget:withObject: method. In OS X v10.5 and later, you can create instances of NSThread and start them at a later time using the start method.
In OS Xv10.5, the NSThread class supports semantics similar to those of NSOperation for monitoring the runtime condition of a thread. You can use these semantics to cancel the execution of a thread or determine if the thread is still executing or has finished its task. Canceling a thread requires support from your thread code; see the description for cancel for more information.
Subclassing Notes
In OS X v10.5 and later, you can subclass NSThread and override the main method to implement your thread’s main entry point. If you override main, you do not need to invoke the inherited behavior by calling super.
Starts the receiver.
- (void)start
This method spawns the new thread and invokes the receiver’s main method on the new thread. If you initialized the receiver with a target and selector, the default main method invokes that selector automatically.
If this thread is the first thread detached in the application, this method posts the NSWillBecomeMultiThreadedNotification with object nil to the default notification center.
The main entry point routine for the thread.
- (void)main
The default implementation of this method takes the target and selector used to initialize the receiver and invokes the selector on the specified target. If you subclass NSThread, you can override this method and use it to implement the main body of your thread instead. If you do so, you do not need to invoke super.
You should never invoke this method directly. You should always start your thread by invoking the start method.