使用NSOperation+NSOperationQueue实现多任务网络连接

在网络应用程序中,经常需要多任务连接来提高程序的性能。比如多任务下载,多任务HTTP请求等,即线程控制模型中的工作群模型。使用 NSOperation 可以很容易实现这个功能。下面就以使用NSOperation处理并行的HTTP请求为例子,说明其用法。
首先准备一个 NSOperation 的子类,用于处理 HTTP 请求。

1 @interface RequestOperation : NSOperation {
2 NSURLRequest* _request;
3 NSMutableData* _data;
4 }
5 
6 - (id)initWithRequest:(NSURLRequest *)request;
7 
8 @end

 


下面是实现:

 1 @implementation RequestOperation
 2 
 3 - (id)initWithRequest:(NSURLRequest *)request {
 4 if (self = [self init]) {
 5 _request = [request retain];
 6 _data = [[NSMutableData data] retain];
 7 }
 8 return self;
 9 }
10 
11 - (void)dealloc {
12 [_request release];
13 [_data release];
14 [super dealloc];
15 }
16 
17 // 如果不载下面的函数,会出错
18 - (BOOL)isConcurrent {
19 return YES;
20 }
21 
22 // 开始处理
23 - (void)start {
24 if (![self isCancelled]) {
25 // 以异步方式处理事件
26 [NSURLConnection connectionWithRequest:_request delegate:self];
27 }
28 }
29 
30 // 取得数据
31 - (void)connection:(NSURLConnection*)connection
32 didReceiveData:(NSData*)data {
33 // 添加数据
34 [_data appendData:data];
35 }
36 
37 // HTTP请求结束
38 - (void)connectionDidFinishLoading:(NSURLConnection*)connection {
39 }
40 
41 @end

 



如果没有重载 isConcurrent 函数,缺省是返回NO,就是说只能以同步的方式处理。而如果又使用了connectionWithRequest:delegate: 以异步方式处理事件后,会产生下面的错误信息:

_NSAutoreleaseNoPool(): Object 0x18a140 of class NSURLConnection autoreleased with no pool in place - just leaking

然后在你的 Controller 类中用 NSOperationQueue 来处理各个任务。

1 @interface xxViewController : UIViewController {
2 NSOperationQueue* _queue;
3 }
4 
5 @end

 




 1 @implementation xxViewController
 2 
 3 - (IBAction)buttonClicked:(id) sender {
 4 _queue = [[NSOperationQueue alloc] init];
 5 // 第一个请求
 6 NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];
 7 RequestOperation* operation = [[RequestOperation alloc] initWithRequest:request];
 8 [operation autorelease];
 9 // 第二个请求
10 NSURLRequest* request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.yahoo.co.jp"]];
11 RequestOperation* operation2 = [[RequestOperation alloc] initWithRequest:request2];
12 [operation2 autorelease];
13 // 开始处理
14 [_queue addOperation:operation];
15 }
16 
17 @end

 


以上,用 NSOperation 来并行处理不同的任务,使用 NSOperationQueue 来控制复数的 NSOperation,并且可以限制Queue的大小,而不是无限制的使用任务。当一个任务完成,就执行待机中的任务。

经过测试,上面的方法不可行,因为在线程中无法使用异步的方式去请求http
改过之后的例子如下

 1 // RequestOperation.m
 2 
 3 #import "RequestOperation.h"
 4 
 5 
 6 @implementation RequestOperation
 7 
 8 - (id)initWithURL:(NSString *)url
 9 {
10 data = [[NSMutableData data] retain];
11 self = [super init];
12 if (self)
13 {
14 targetURL = url;
15 }
16 return self;
17 }
18 
19 - (void)showData:(NSData *)theData encoding:(NSString *)encoding {
20 if (data != theData) {
21 [data release];
22 data = [theData retain];
23 
24 // NSURLResponse's encoding is an IANA string. Use CF utilities to convert it to a CFStringEncoding then a NSStringEncoding
25 NSStringEncoding nsEncoding = NSUTF8StringEncoding; // default to UTF-8
26 if (encoding) {
27 CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)encoding);
28 if (cfEncoding != kCFStringEncodingInvalidId) {
29 nsEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
30 }
31 }
32 NSString *displayString = [[NSString alloc] initWithData:data encoding:nsEncoding];
33 //NSLog(@"body:%@", displayString);
34 [displayString release];
35 }
36 }
37 
38 - (void)main {
39 NSLog(@"url:%@", targetURL);
40 // Synchronously grab the data
41 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL]];
42 NSError *error;
43 NSURLResponse *response;
44 NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
45 [self showData:result encoding:[response textEncodingName]];
46 if (!result) {
47 NSLog(@"error:",[error localizedDescription]);
48 }
49 NSLog(@"%@ is download.", targetURL);
50 }
51 
52 - (void)dealloc {
53 [data release];
54 [super dealloc];
55 }
56 
57 @end
58 
59 界面部分代码
60 NSOperationQueue* _queue;
61 - (IBAction)buttonClicked:(id) sender {
62 NSLog(@"start.");
63 _queue = [[NSOperationQueue alloc] init];
64 [_queue setMaxConcurrentOperationCount:2];
65 RequestOperation* operation1 = [[RequestOperation alloc] initWithURL:@"http://www.google.com"];
66 [operation1 autorelease];
67 RequestOperation* operation2 = [[RequestOperation alloc] initWithURL:@"http://www.yahoo.co.jp"];
68 [operation2 autorelease];
69 RequestOperation* operation3 = [[RequestOperation alloc] initWithURL:@"http://new.sina.com.cn"];
70 [operation3 autorelease];
71 RequestOperation* operation4 = [[RequestOperation alloc] initWithURL:@"http://www.163.com"];
72 [operation4 autorelease];
73 RequestOperation* operation5 = [[RequestOperation alloc] initWithURL:@"http://www.sohu.com"];
74 [operation5 autorelease];
75 RequestOperation* operation6 = [[RequestOperation alloc] initWithURL:@"http://www.csdn.net"];
76 [operation6 autorelease];
77 RequestOperation* operation7 = [[RequestOperation alloc] initWithURL:@"http://www.yahoo.com.tw"];
78 [operation7 autorelease];
79 // 开始处理
80 [_queue addOperation:operation1];
81 [_queue addOperation:operation2];
82 [_queue addOperation:operation3];
83 [_queue addOperation:operation4];
84 [_queue addOperation:operation5];
85 [_queue addOperation:operation6];
86 [_queue addOperation:operation7];
87 NSLog(@"end.");
88 }

转载于:https://www.cnblogs.com/evolution-cc/archive/2012/08/02/2620381.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值