GVKun编程网logo

objective-c – 启动自动释放的NSOperationQueue是否有危险?

11

对于想了解objective-c–启动自动释放的NSOperationQueue是否有危险?的读者,本文将是一篇不可错过的文章,并且为您提供关于CocoaTutorial:NSOperationand

对于想了解objective-c – 启动自动释放的NSOperationQueue是否有危险?的读者,本文将是一篇不可错过的文章,并且为您提供关于Cocoa Tutorial: NSOperation and NSOperationQueue、Cocoa: NSOperation和NSOperationQueue、iOS GCD 与 NSOperationQueue对比、ios – NSOperationQueue addOperations waitUntilFinished的有价值信息。

本文目录一览:

objective-c – 启动自动释放的NSOperationQueue是否有危险?

objective-c – 启动自动释放的NSOperationQueue是否有危险?

我有一个任务需要相当长的时间,应该在后台运行.根据文档,可以使用NSOperationQueue完成此操作.但是,我不想保留NSOperationQueue的类全局副本,因为我真的只使用它来执行该任务.因此,我只是将其设置为自动释放,并希望在任务完成之前不会释放它.有用.
喜欢这个:
NSInvocationoperation *theTask = [NSInvocationoperation alloc];theTask = [theTask initWithTarget:self                         selector:@selector(doTask:)                           object:nil];NSOperationQueue *operationQueue = [[NSOperationQueue new] autorelease];[operationQueue addOperation:theTask];[theTask release];

我很担心,但是.这是否保证工作?或者可能在某个时候运行Queue被取消分配,并采用该方法吗?

解决方法

在文档中没有什么可以说出NSOperationQueue发布时会发生什么.假设不能保证该任务将被执行是最安全的.

Cocoa Tutorial: NSOperation and NSOperationQueue

Cocoa Tutorial: NSOperation and NSOperationQueue

 

Threading is hard in any language. And what is worse,when it goes wrong,it usually goes wrong in a very bad way. Because of this,programmers either avoid threading completely (and refer to it as the spawn of the devil) or spend a LOT of time making sure that everything is perfect.

Fortunately,Apple has made a lot of progress in OS X 10.5 Leopard. NSThread itself has received a number of very useful new methods that make threading easier. In addition,they have introduced two new objects: NSOperation and NSOperationQueue.

In this Tutorial I will walk through a basic example that shows how to use these new Objects and how they make multi-threading your application nearly trivial.

You can get the example project here: Async Downloader Example Project

In this tutorial,I will demonstrate one way in which to use NSOperation and NSOperationQueue to handle tasks that are best performed on background threads. The intent of this tutorial is to demonstrate a basic use of these classes and is not intentioned to be the only way to use them.

If you are familiar with Java,or one of its variants,the NSOperation object is very similar to the java.lang.Runnable interface. Like,in Java’s Runnable interface,the NSOperation object is designed to be extended. Also like Java’s Runnable,there is a minimum of one method to override. For NSOperation that method is -(void)main. One of the easiest ways to use an NSOperation is to load it into an NSOperationQueue. As soon as the operation is loaded into the queue,the queue will kick it off and begin processing. As soon as the operation is complete the queue will release it.

NSOperation Example

In this example,I have written an NSOperation that fetches a webpage as a string,parses it into an NSXMLDocument and then passes that NSXMLDocument back to the main thread in the application before completing.

PageLoadOperation.h

1
2
3
4
5
6
7
8
9
10
11
12
#import <Cocoa/Cocoa.h>
 
 
@interface PageLoadOperation : NSOperation {
    NSURL *targetURL;
}
 
@property(retain) NSURL *targetURL;
 
- (id)initWithURL:(NSURL*)url;
 
@end

PageLoadOperation.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import "PageLoadOperation.h"
#import "AppDelegate.h"
 
@implementation PageLoadOperation
 
@synthesize targetURL;
 
- (id)initWithURL:(NSURL*)url;
{
    if (![super init]) return nil;
    [self setTargetURL:url];
    return self;
}
 
- (void)dealloc {
    [targetURL release],targetURL = nil;
    [super dealloc];
}
 
- (void)main {
    Nsstring *webpageString = [[[Nsstring alloc] initWithContentsOfURL:[self targetURL]] autorelease];
 
    NSError *error = nil;
    NSXMLDocument *document = [[NSXMLDocument alloc] initWithXMLString:webpageString 
                                                              options:NSXMLDocumentTidyHTML 
                                                                error:&error];
    if (!document) {
        NSLog(@"%s Error loading document (%@): %@",_cmd,[[self targetURL] absoluteString],error);
        return;
    }	
 
    [[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:)
                                           withObject:document
                                        waitUntilDone:YES];
    [document release];
}
 
@end

As you can see,this class is very simple. It accepts a URL in the init and stores it. When the main method is called it constructs a string from the URL and then passes that string into the init of an NSXMLDocument. If there is no error with the loading of the xml document,it is then passed back to the AppDelegate,on the main thread,and the task is complete. When the main method of the NSOperation ends the queue will automatically release the object.

AppDelegate.h

1
2
3
4
5
6
7
8
9
10
#import <Cocoa/Cocoa.h>
 
@interface AppDelegate : NSObject {
	NSOperationQueue *queue;
}
 
+ (id)shared;
- (void)pageLoaded:(NSXMLDocument*)document;
 
@end

AppDelegate.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#import "AppDelegate.h"
#import "PageLoadOperation.h"
 
@implementation AppDelegate
static AppDelegate *shared;
static NSArray *urlArray;
 
- (id)init
{
    if (shared) {
        [self autorelease];
        return shared;
    }
    if (![super init]) return nil;
 
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addobject:@"http://www.google.com"];
    [array addobject:@"http://www.apple.com"];
    [array addobject:@"http://www.yahoo.com"];
    [array addobject:@"http://www.zarrastudios.com"];
    [array addobject:@"http://www.macosxhints.com"];
    urlArray = array;
 
    queue = [[NSOperationQueue alloc] init];
    shared = self;
    return self;
}
 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    for (Nsstring *urlString in urlArray) {
        NSURL *url = [NSURL URLWithString:urlString];
        PageLoadOperation *plo = [[PageLoadOperation alloc] initWithURL:url];
        [queue addOperation:plo];
        [plo release];
    }
}
 
- (void)dealloc
{
    [queue release],queue = nil;
    [super dealloc];
}
 
+ (id)shared;
{
    if (!shared) {
        [[AppDelegate alloc] init];
    }
    return shared;
}
 
- (void)pageLoaded:(NSXMLDocument*)document;
{
    NSLog(@"%s Do something with the XMLDocument: %@",document);
}
 
@end

In this example AppDelegate,two things are occurring. First,in the init method,the NSOperationQueue is being initialized and an array of urls is being loaded. Then when the application has completed its load,the applicationDidFinishLaunching: method is called by the NSApplication instance and the AppDelegate loops over the urls,creating a task for each one and loading those tasks into the NSOperationQueue. As soon as each item is loaded into the queue the queue will kick it off by assigning it to a NSThread and the thread will then run the main method of the operation. Once the operation is complete the thread will report back to the queue and the queue will release the operation.

NSOperationQueue Concurrency

In this very simple example,it is quite difficult to load up the queue with enough objects to actually see it running them in parallel. However,if you run tasks that take more time than these,you will see that the queue will run all of the tasks at the same time. Fortunately,if you want to limit how many tasks are running in parallel you can alter the init method in the App Delegate as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (id)init
{
    if (shared) {
        [self autorelease];
        return shared;
    }
    if (![super init]) return nil;
 
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addobject:@"http://www.google.com"];
    [array addobject:@"http://www.apple.com"];
    [array addobject:@"http://www.yahoo.com"];
    [array addobject:@"http://www.zarrastudios.com"];
    [array addobject:@"http://www.macosxhints.com"];
    urlArray = array;
    queue = [[NSOperationQueue alloc] init];
    [queue setMaxConcurrentOperationCount:2];
    shared = self;
    return self;
}

In this updated init method,the queue is throttled down to 2 operations running at the same time. The rest of the operations will wait until one of the first two is completed and then they will get an opportunity to run until the queue is empty.

Conclusion

That is the NSOperation and NSOperationQueue in its most basic form. You will note that most of the code in this example has nothing to do with the building up or using of the NSOperation or the NSOperationQueue. The actual code required to use the NSOperation is amazingly small. Yet with this small amount of code you can easily start using multiple threads in your application and provide a better experience for the user and be able to fine tune those complicated tasks.

Cocoa: NSOperation和NSOperationQueue

Cocoa: NSOperation和NSOperationQueue

    Cocoa: NSOperation和NSOperationQueue

    在任何语言中多线程处理都是麻烦的。更糟糕的是如果出错了往往会以很坏的方式出错。鉴于此,程序员要么完全避免使用多线程(把它当做邪恶之源),要么发很长的时间来确保每个方面都很完美。

    庆幸的是, Apple在OS X 10.5 Leopard上做了很多改进。NSThread本身就新增了很多新的方法,从而使得多线程变得更加容易。此外还新增了NSOperation和NSOperationQueue两个类。该教程通过一个简单的实例来介绍如何使用这些新增类并如何让多线程的应用变得小菜一碟。
   你可以从此获取该项目的实例代码: Async Downloader Example Project
    在该教程中,我会介绍一种使用 NSOperation和NSOperationQueue在后台线程中很好地处理任务的方法。该教程的目标是介绍这些类的使用,但并不排除使用它们的其他方法。
如果你熟悉 Java或一个它的变种语言,NSOperation就和java.lang.Runnable接口很相似。和Java的Runnable一样,NSOperation也是设计用来扩展的,并且最低仅需重写一个方法。对于NSOperation这个方法是-(void)main。一个使用NSOperation的最简单方法就是将其放入NSOperationQueue中。一旦一个操作被加入队列,该队列就会启动并开始处理它。一旦该操作完成队列就会释放它。
 
NSOperation实例
在该实例中,我编写了一段获取网页内容的字符串,然后解析成 NSXMLDocument对象并在结束前传回应用主线程。
PageLoadOperation.h
 
 
 
  1. #import <Cocoa/Cocoa.h>  
  2. @interface PageLoadOperation : NSOperation {  
  3.     NSURL *targetURL;  
  4. }  
  5.  
  6. @property(retain) NSURL *targetURL;  
  7.  
  8. - (id)initWithURL:(NSURL*)url;  
  9.  
  10. @end 

PageLoadOperation.m

 
 
  1. #import "PageLoadOperation.h" 
  2. #import "AppDelegate.h" 
  3.    
  4. @implementation PageLoadOperation  
  5.    
  6. @synthesize targetURL;  
  7.    
  8. - (id)initWithURL:(NSURL*)url;  
  9. {  
  10.     if (![super init]) return nil;  
  11.     [self setTargetURL:url];  
  12.     return self;  
  13. }  
  14.    
  15. - (void)dealloc {  
  16.     [targetURL release], targetURL = nil;  
  17.     [super dealloc];  
  18. }  
  19.    
  20. - (void)main {  
  21.     Nsstring *webpageString = [[[Nsstring alloc] initWithContentsOfURL:[self targetURL]] autorelease];  
  22.    
  23.     NSError *error = nil;  
  24.     NSXMLDocument *document = [[NSXMLDocument alloc] initWithXMLString:webpageString   
  25.                                                               options:NSXMLDocumentTidyHTML   
  26.                                                                 error:&error];  
  27.     if (!document) {  
  28.         NSLog(@"%s Error loading document (%@): %@", _cmd, [[self targetURL] absoluteString], error);  
  29.         return;  
  30.     }     
  31.    
  32.     [[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:)  
  33.                                            withObject:document  
  34.                                         waitUntilDone:YES];  
  35.     [document release];  
  36. }  
  37.    
  38. @end 
我们可以看到,这个类很简单。它在 init方法中接受一个URL并保存起来。在调用main方法的时候它就从URL中构建一个字符串并传给NSXMLDocument的init方法。如果在加载xml文档过程中没有发生错误,该文档就会被传回到主线程的AppDelegate,然后任务结束。队列会在NSOperation的main方法结束后自动释放该对象。
AppDelegate.h
 
 
 
  1. #import <Cocoa/Cocoa.h>  
  2.    
  3. @interface AppDelegate : NSObject {  
  4.     NSOperationQueue *queue;  
  5. }  
  6.    
  7. + (id)shared;  
  8. - (void)pageLoaded:(NSXMLDocument*)document;  
  9.    
  10. @end 
AppDelegate.m
 
 
 
  1. #import "AppDelegate.h" 
  2. #import "PageLoadOperation.h" 
  3.    
  4. @implementation AppDelegate  
  5. static AppDelegate *shared;  
  6. static NSArray *urlArray;  
  7.    
  8. - (id)init  
  9. {  
  10.     if (shared) {  
  11.         [self autorelease];  
  12.         return shared;  
  13.     }  
  14.     if (![super init]) return nil;  
  15.    
  16.     NSMutableArray *array = [[NSMutableArray alloc] init];  
  17.     [array addobject:@"http://www.google.com"];  
  18.     [array addobject:@"http://www.apple.com"];  
  19.     [array addobject:@"http://www.yahoo.com"];  
  20.     [array addobject:@"http://www.zarrastudios.com"];  
  21.     [array addobject:@"http://www.macosxhints.com"];  
  22.     urlArray = array;  
  23.    
  24.     queue = [[NSOperationQueue alloc] init];  
  25.     shared = self;  
  26.     return self;  
  27. }  
  28.    
  29. - (void)applicationDidFinishLaunching:(NSNotification *)aNotification  
  30. {  
  31.     for (Nsstring *urlString in urlArray) {  
  32.         NSURL *url = [NSURL URLWithString:urlString];  
  33.         PageLoadOperation *plo = [[PageLoadOperation alloc] initWithURL:url];  
  34.         [queue addOperation:plo];  
  35.         [plo release];  
  36.     }  
  37. }  
  38.    
  39. - (void)dealloc  
  40. {  
  41.     [queue release], queue = nil;  
  42.     [super dealloc];  
  43. }  
  44.    
  45. + (id)shared;  
  46. {  
  47.     if (!shared) {  
  48.         [[AppDelegate alloc] init];  
  49.     }  
  50.     return shared;  
  51. }  
  52.    
  53. - (void)pageLoaded:(NSXMLDocument*)document;  
  54. {  
  55.     NSLog(@"%s Do something with the XMLDocument: %@", document);  
  56. }  
  57.    
  58. @end 
在实例中 AppDelegate做了两件事。其一是在init方法中初始化了NSOperationQueue并载入了一个urls数组。在应用结束加载时NSApplication 实例会调用applicationDidFinishLaunching:方法,AppDelegate就遍历每个url并创建相应的任务,然后将任务加入队列中。在队列中每加入一个人后,队列都会为其分配一个NSThread来启动它,线程就会运行操作的main方法。一旦操作完成,线程就会报告给队列以让队列释放该操作。
 
NSOperationQueue的并发
在这个简单的实例中,由于很难再队列中加入足够多的任务使得我们很难看到它们是并发运行的。但如果你的任务需要更多的时间,你就可以看到队列是同时运行所有的任务。如果你想限制并行运行的任务数目,你可以在 AppDelegate的init方法中做如下修改。
 
 
 
  1. - (id)init  
  2. {  
  3.     if (shared) {  
  4.         [self autorelease];  
  5.         return shared;  
  6.     }  
  7.     if (![super init]) return nil;  
  8.    
  9.     NSMutableArray *array = [[NSMutableArray alloc] init];  
  10.     [array addobject:@"http://www.google.com"];  
  11.     [array addobject:@"http://www.apple.com"];  
  12.     [array addobject:@"http://www.yahoo.com"];  
  13.     [array addobject:@"http://www.zarrastudios.com"];  
  14.     [array addobject:@"http://www.macosxhints.com"];  
  15.     urlArray = array;  
  16.     queue = [[NSOperationQueue alloc] init];  
  17.     [queue setMaxConcurrentOperationCount:2];  
  18.     shared = self;  
  19.     return self;  
在这个修改的 init方法中,队列被限制只能同时运行两个操作。剩余的操作就需要等待之前的两个操作有一个完成后才有机会被运行。
 
结论
这是 NSOperation和NSOperationQueue最基本的使用。你可以注意到该实例的大部分代码和NSOperation和NSOperationQueue 的设定和使用无关。NSOperation所需要的代码是惊人地少。但是通过这少量的代码你就可以在你的应用中轻松地使用多线程以为用户提供更好的用户体验并可以更好地优化复杂任务。
原文链接:http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/

iOS GCD 与 NSOperationQueue对比

iOS GCD 与 NSOperationQueue对比

  • NSOperationQueue 是在GCD基础上实现的,只不过是GCD更高一层的抽象。
  • GCD 只支持FIFO 的队列, 而NSOperationQueue可以调整队列的执行顺序。(通过调整权重)
  • NSOperationQueue可以在Operation间设置依赖关系,而GCD不可以。 如果一个Operation依赖另一个Operation所产生的数据的化,你可以设置一个Operation依赖于另一个Operation来实现, NSOperationQueue可以根据依赖关系,可以以正确的顺序执行Queue中的Operation。
  • NSOperationQueue支持KVO。 这就意味着你可以观察任务的状态属性。

以上几点并不是说在任何处理多任务时一定要选择NSOperationQueue, 因为NSOperationQueue在执行速度上会比GCD慢。

ios – NSOperationQueue addOperations waitUntilFinished

ios – NSOperationQueue addOperations waitUntilFinished

嗨,我正在使用 Swift构建一个应用程序.我需要按特定顺序处理通知.因此我尝试使用addOperations waitUntilFinished.

这是我做的:

let oldify = NSOperation()
    oldify.completionBlock = {
println("oldify")
}
let appendify = NSOperation()
    appendify.completionBlock = {
println("appendify")
}
let nettoyify = NSOperation()
    nettoyify.completionBlock = {
println("nettoyify")
}
NSOperationQueue.mainQueue().maxConcurrentOperationCount = 1
NSOperationQueue.mainQueue().addOperations([oldify,appendify,nettoyify],waitUntilFinished: true)

使用此代码,没有任何操作正在执行.当我尝试这样做时:

NSOperationQueue.mainQueue().maxConcurrentOperationCount = 1
NSOperationQueue.mainQueue().addOperation(oldify)
NSOperationQueue.mainQueue().addOperation(appendify)
NSOperationQueue.mainQueue().addOperation(nettoyify)

操作执行但不按正确的顺序执行.

有谁知道我做错了什么?我对NSOperations迅速而又全新地充满信心

解决方法

几个问题:

>您正在检查完成块处理程序的行为.正如completionBlock文档所说:

The exact execution context for your completion block is not guaranteed but is typically a secondary thread. Therefore,you should not use this block to do any work that requires a very specific execution context.

队列将自己管理操作,但不管理它们的完成块(缺少确保操作在其completionBlock启动之前完成).因此,底线,不要做任何关于(a)运行完成块的时间,(b)一个操作的completionBlock与其他操作或其completionBlock块等的关系,以及(c)它们在哪个线程上执行的假设. .
>操作通常按照添加到队列的顺序执行.但是,如果添加一组操作,则文档不会正式保证它们按照它们在该数组中出现的顺序排队.因此,您可能希望一次添加一个操作.
>话虽如此,文档继续警告我们:

An operation queue executes its queued operation objects based on their priority and readiness. If all of the queued operation objects have the same priority and are ready to execute when they are put in the queue—that is,their isReady method returns YES—they are executed in the order in which they were submitted to the queue. However,you should never rely on queue semantics to ensure a specific execution order of operation objects. Changes in the readiness of an operation can change the resulting execution order. If you need operations to execute in a specific order,use operation-level dependencies as defined by the NSOperation class.

要建立显式依赖关系,您可能会执行以下操作:

let oldify = NSBlockOperation() {
    NSLog("oldify")
}
oldify.completionBlock = {
    NSLog("oldify completion")
}

let appendify = NSBlockOperation() {
    NSLog("appendify")
}
appendify.completionBlock = {
    NSLog("appendify completion")
}

appendify.addDependency(oldify)

let nettoyify = NSBlockOperation() {
    NSLog("nettoyify")
}
nettoyify.completionBlock = {
    NSLog("nettoyify completion")
}

nettoyify.addDependency(appendify)

let queue = NSOperationQueue()
queue.addOperations([oldify,waitUntilFinished: false)

>顺便说一下,正如您将在上面看到的那样,您不应该将操作与waitUntilFinished一起添加到主队列中.可以随意将它们添加到不同的队列,但不要使用waitUntilFinished选项从串行队列调度回自身.

关于objective-c – 启动自动释放的NSOperationQueue是否有危险?的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Cocoa Tutorial: NSOperation and NSOperationQueue、Cocoa: NSOperation和NSOperationQueue、iOS GCD 与 NSOperationQueue对比、ios – NSOperationQueue addOperations waitUntilFinished的相关知识,请在本站寻找。

本文标签: