Objective-c Nsoperation multithreaded Class basic use Guide _ios

Source: Internet
Author: User


Nsoperation



First, Nsoperation
1. Introduction
The Nsoperation instance encapsulates the required operations and the data needed to perform the operation, and can perform this operation concurrently or in a non concurrency manner.
The nsoperation itself is an abstract base class, so you must use its subclasses, and there are 2 ways to use nsoperation subclasses:
The 1> Foundation framework provides two specific subclasses directly for our use: Nsinvocationoperation and Nsblockoperation
2> Custom subclass Inherits Nsoperation, realizes the internal corresponding method



2. Perform operations
Nsoperation calls the Start method to begin the operation, and the Nsoperation object executes synchronously by default, which is executed directly in the thread that calls the Start method. The Isconcurrent method of the Nsoperation object tells us whether the operation is synchronous or asynchronous, relative to the thread calling the Start method. The Isconcurrent method returns no by default, indicating that the action is performed synchronously with the calling thread



3. Cancel operation
After the operation begins execution, the action is performed by default until it is completed, and we can call Cancel to undo the operation


 code as follows:

[Operation Cancel];

4. The execution of the listening operation
If we want to do something after a nsoperation executes, call the Nsoperation Setcompletionblock method to set what you want to do
code as follows:

Operation.completionblock = ^ () {
NSLog (@ "execution completed");
};

Or
 code as follows:

[Operation Setcompletionblock:^ () {
NSLog (@ "execution completed");
}];

Second, nsinvocationoperation
1. Introduction
Create an operation based on an object and selector. If you already have existing methods to perform the tasks you need, you can use this class





2. Create and perform actions


 code as follows:

This action is: Invoke the Self's Run method
Nsinvocationoperation *operation = [[Nsinvocationoperation alloc] initwithtarget:self selector: @selector (Run) object: NIL];
Start the task (synchronous execution)
[Operation start];

Third, Nsblockoperation
1. Introduction
The ability to execute one or more block objects concurrently, after all the associated blocks have been executed, the operation is completed





2. Create and perform actions


 code as follows:

Nsblockoperation *operation = [Nsblockoperation blockoperationwithblock:^ () {
NSLog (@ "Executes a new operation, thread:%@", [Nsthread CurrentThread]);
}];
Start the task (here or synchronously)
[Operation start];

3. Add block operation by Addexecutionblock method
 code as follows:

Nsblockoperation *operation = [Nsblockoperation blockoperationwithblock:^ () {
NSLog (@ "Perform 1th operation, thread:%@", [Nsthread CurrentThread]);
}];

[Operation Addexecutionblock:^ () {
NSLog (@ "also executes 1 new operations, Threads:%@", [Nsthread CurrentThread]);
}];

[Operation Addexecutionblock:^ () {
NSLog (@ "also executes 1 new operations, Threads:%@", [Nsthread CurrentThread]);
}];

[Operation Addexecutionblock:^ () {
NSLog (@ "also executes 1 new operations, Threads:%@", [Nsthread CurrentThread]);
}];

Start a task
[Operation start];

Print the information as follows:




2013-02-02 21:38:46.102 THREAD[4602:C07] has also performed 1 new operations, Thread: <nsthread:0x7121d50>{name = (null), num = 1} 
2013-02-02 21:38:46.102 thread[4602:3f03] has also performed 1 new operations, Thread: <nsthread:0x742e1d0>{name = (null), num = 5} 
2013-02-02 21:38:46.102 THREAD[4602:1B03] Perform the 1th operation, thread: <nsthread:0x742de50>{name = (null), num = 3} 
2013-02-02 21:38:46.102 thread[4602:1303] has also performed 1 new operations, Thread: <nsthread:0x7157bf0>{name = (null), num = 4} 


As you can see, these 4 blocks are executed concurrently, which is executed in different threads, and the NUM attribute can be considered as the ID of the thread



Iv. Custom Nsoperation
1. Introduction
If Nsinvocationoperation and Nsblockoperation objects don't meet your needs, you can directly inherit nsoperation and add any behavior you want. The amount of work required to inherit depends largely on whether you want to implement concurrency or concurrent nsoperation. It is much simpler to define nsoperation than to overload-(void) Main, which performs the main task within this method and responds correctly to cancellation events; For concurrent nsoperation, you must rewrite Nsoperation's several basic methods for implementation (here is a brief introduction to concurrency Nsoperation)



2. Non-concurrent Nsoperation
For example, called downloadoperation, to download pictures.
1> inherits Nsoperation, overrides Main method, Executive Director service
DownloadOperation.h


 code as follows:

#import <Foundation/Foundation.h>
@protocol downloadoperationdelegate;

@interface downloadoperation:nsoperation
The URL path of the picture
@property (nonatomic, copy) NSString *imageurl;
Agent
@property (nonatomic, retain) id<downloadoperationdelegate> delegate;

-(ID) Initwithurl: (nsstring *) URL delegate: (id<downloadoperationdelegate>) delegate;
@end

 code as follows:

Picture Download Protocol
@protocol downloadoperationdelegate <NSObject>
-(void) Downloadfinishwithimage: (UIImage *) image;
@end

Downloadoperation.m
 code as follows:

#import "DownloadOperation.h"

@implementation Downloadoperation
@synthesize delegate = _delegate;
@synthesize imageUrl = _imageurl;

Class
-(ID) Initwithurl: (nsstring *) URL delegate: (id<downloadoperationdelegate>) Delegate {
if (self = [super init]) {
Self.imageurl = URL;
Self.delegate = delegate;
}
return self;
}
Free memory
-(void) Dealloc {
[Super Dealloc];
[_delegate release];
[_imageurl release];
}

Executive Director Service
-(void) Main {
Creates a new automatic free pool, and if the operation is performed asynchronously, it will not be able to access the main thread's automatic free pool
@autoreleasepool {
// ....
}
}
@end

2> correctly respond to cancellation events
After the operation begins execution, the task is performed until it is completed, or the operation is explicitly canceled. Cancellation may occur at any time, even before operation executes. Although Nsoperation provides a way for the application to cancel an operation, it is our own business to recognize the cancellation event. If operation is terminated directly, you may not be able to recycle all allocated memory or resources. So the operation object needs to detect the cancellation event and gracefully exit the execution
The Nsoperation object needs to periodically call the IsCancelled method to detect if the operation has been canceled, and if Yes (indicates canceled), exit execution immediately. You need to support cancellation whether you are customizing the Nsoperation subclass or using the two specific subclasses provided by the system. The IsCancelled method itself is very lightweight and can be invoked frequently without generating significant performance losses
You may need to call iscancelled in the following places:
* Before any actual work is performed
* During each iteration of the loop, if each iteration is relatively long you may need to invoke multiple
* Anywhere in the code that is relatively easy to abort
Downloadoperation's Main method is implemented as follows
 code as follows:

-(void) Main {
Creates a new automatic free pool, and if the operation is performed asynchronously, it will not be able to access the main thread's automatic free pool
@autoreleasepool {
if (self.iscancelled) return;

Get Picture data
Nsurl *url = [Nsurl URLWITHSTRING:SELF.IMAGEURL];
NSData *imagedata = [NSData Datawithcontentsofurl:url];

if (self.iscancelled) {
url = nil;
ImageData = nil;
Return
}

Initializing a picture
UIImage *image = [UIImage imagewithdata:imagedata];

if (self.iscancelled) {
image = Nil;
Return
}

if ([Self.delegate respondstoselector: @selector (downloadfinishwithimage:)]) {
Pass the picture data back to the main thread
[(NSObject *) self.delegate performselectoronmainthread: @selector (downloadfinishwithimage:) withobject:image Waituntildone:no];
}
}
}





Nsoperationqueue
First, Introduction
a Nsoperation object can perform a task by invoking the Start method, which is performed synchronously by default. You can also add nsoperation to a Nsoperationqueue (action queue) and execute it asynchronously.
To create an action queue:


 code as follows:

Nsoperationqueue *queue = [[Nsoperationqueue alloc] init];

Second, add nsoperation to Nsoperationqueue
1. Add a operation
 code as follows:

[Queue addoperation:operation];

2. Add a set of operation
 code as follows:

[Queue addoperations:operations Waituntilfinished:no];

3. Add a block form of operation
 code as follows:

[Queue addoperationwithblock:^ () {
NSLog (@ "Execute a new operation, thread:%@", [Nsthread CurrentThread]);
}];

After Nsoperation is added to the queue, it is usually run in a short time. However, if there is a dependency, or the entire queue is paused, it may also need to wait.
Note: After Nsoperation is added to the queue, never modify the state of the Nsoperation object. Because Nsoperation objects can run at any time, changing the dependencies or data of a Nsoperation object can have a detrimental effect. You can only view the status of the Nsoperation object, such as whether it is running, waiting to run, completed, etc.





Third, add nsoperation dependent objects
1. When a Nsoperation object relies on the completion of other Nsoperation objects, one or more dependent objects can be added through the Adddependency method, and only all dependent objects have completed operations. The current Nsoperation object does not begin the operation. In addition, the Removedependency method is used to delete the dependent objects.


 code as follows:

[Operation2 Adddependency:operation1];

Dependencies are not limited to nsoperation objects in the same queue, nsoperation objects manage their dependencies, so it is entirely possible to create dependencies between different queue Nsoperation objects








The only limitation is the inability to create circular dependencies, such as a dependent b,b dependency A, which is wrong



2. Dependencies affect the order in which the Nsoperation objects are executed in the queue, as shown in the following example:
1> No dependencies Set


 code as follows:

Nsoperationqueue *queue = [[Nsoperationqueue alloc] init];

Nsblockoperation *operation1 = [Nsblockoperation blockoperationwithblock:^ () {
NSLog (@ "Perform 1th operation, thread:%@", [Nsthread CurrentThread]);
}];

Nsblockoperation *operation2 = [Nsblockoperation blockoperationwithblock:^ () {
NSLog (@ "Perform 2nd operation, thread:%@", [Nsthread CurrentThread]);
}];

[Queue Addoperation:operation1];
[Queue Addoperation:operation2];

Print information:




2013-02-03 00:21:35.024 Thread[5616:3d13] Perform the 1th operation, thread: <nsthread:0x7658570>{name = (null), num = 3} 
2013-02-03 00:21:35.063 thread[5616:1303] Perform the 2nd operation, thread: <nsthread:0x765a2e0>{name = (null), num = 4} 


As you can see, the default is done in the order of addition, execute Operation1 first, then execute Operation2



2> Set Dependencies


 code as follows:

Nsoperationqueue *queue = [[Nsoperationqueue alloc] init];

Nsblockoperation *operation1 = [Nsblockoperation blockoperationwithblock:^ () {
NSLog (@ "Perform 1th operation, thread:%@", [Nsthread CurrentThread]);
}];

Nsblockoperation *operation2 = [Nsblockoperation blockoperationwithblock:^ () {
NSLog (@ "Perform 2nd operation, thread:%@", [Nsthread CurrentThread]);
}];
Operation1 relies on Operation2
[Operation1 Adddependency:operation2];

[Queue Addoperation:operation1];
[Queue Addoperation:operation2];

Print information:




2013-02-03 00:24:16.260 THREAD[5656:1B03] Perform the 2nd operation, thread: <nsthread:0x7634490>{name = (null), num = 3} 
2013-02-03 00:24:16.285 thread[5656:1303] Perform the 1th operation, thread: <nsthread:0x9138b50>{name = (null), num = 4} 


It can be seen that the first execution Operation2, and then execute Operation1



Iv. Modifying the order of execution of operations
for operations added to the queue, their order of execution depends on 2 points:
1. First let's see if Nsoperation is ready: Is it ready to be determined by the dependencies of the object?
2. Then determine according to the relative priority of all nsoperation. The priority level is a property of the Operation object itself. By default, all operation have a "normal" priority, but you can use the Setqueuepriority: method to elevate or lower the Operation object's precedence. Precedence can only be applied to operations in the same queue. If the application has multiple operation queue, each queue's priority level is independent of each other. Therefore, low priority operations in different queue may still be executed earlier than higher priority operations.
Note: Precedence is not an alternative to dependencies, but the priority is to determine the order of execution for the operations that are already ready. The dependencies are satisfied first, and then the highest priority is chosen from all prepared operations based on priority.



V. Set the maximum number of concurrent operations for a queue
the maximum number of concurrent operations for the queue, meaning that the queue runs up to several threads at the same time
Although the Nsoperationqueue class is designed for concurrent execution operations, you can force a single queue to perform only one operation at a time. Setmaxconcurrentoperationcount: Method to configure the maximum number of concurrent operations for a queue. A set of 1 means that the queue can perform only one operation at a time. However, the order of operation execution still depends on other factors, such as Operation Readiness and operation priority. Therefore, the serialized operation queue is not identical to the serial dispatch queue in GCD


 code as follows:

Only one action can be performed at a time
Queue.maxconcurrentoperationcount = 1;
or write that.
[Queue setmaxconcurrentoperationcount:1];

Vi. Cancellation of operations
Once added to Operation Queue,queue has this operation object and cannot be deleted, the only thing that can be done is cancel. You can call the Cancel method of the Operation object to cancel a single operation, or you can call the Cancelalloperations method of the operation queue to cancel all operations in the current queue.
 code as follows:

Cancel a single action
[Operation Cancel];

Cancel all operations in the queue
[Queue cancelalloperations];

Vii. waiting for options to complete
For best performance, you should design your application to operate as asynchronously as possible, allowing applications to handle other things as operation is executing. If you need to handle the results of operation completion in the current thread, you can use the Nsoperation waituntilfinished method to block the current thread and wait for the operation to complete. Usually we should avoid writing such code, blocking the current thread may be a simple solution, but it introduces more serial code, limiting the concurrency of the entire application, but also reduces the user experience. Never wait for a operation in the main thread of the application, only in the second or secondary threads. Blocking the main thread will result in the application not responding to the user event, and the application will also behave as unresponsive.
 code as follows:

will block the current thread until a operation has finished executing
[Operation Waituntilfinished];

In addition to waiting for a single operation to complete, you can also wait for all of the operations in a queue, using the Nsoperationqueue waituntilalloperationsarefinished method. Note: When waiting for a queue, other threads that apply can still add operation to the queue, and therefore may add a long wait time.
code as follows:

Blocks the current thread and waits for all operations of the queue to complete
[Queue waituntilalloperationsarefinished];

Viii. Suspension and continuation of the queue
If you want to temporarily suspend operations execution, you can use the queue's setsuspended: method to pause the queue. However, pausing a queue does not cause the executing operation to pause in the middle of a task, simply preventing the dispatch of new operation execution. You can pause a queue to suspend a waiting task in response to a user request. You can call setsuspended again later, depending on the user's request: method to continue operation execution in the queue
 code as follows:

Suspend queue
[Queue Setsuspended:yes];

Continue queue
[Queue Setsuspended:no];




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.