我有一個包含2個NSOperations和設置陸續執行它們一個通過設置setMaxConcurrentOperationCount
爲1問題隊列併發及非併發NSOperations
之一的操作中的是一個標準的非併發操作(一個NSOperationQueue只是一個main
方法),它同步從網絡檢索一些數據(當然在單獨的操作線程上)。另一個操作是併發操作,因爲我需要使用一些必須異步運行的代碼。
問題是,我發現併發操作只有在它被首先添加到隊列中時才起作用。如果它出現在任何非併發操作之後,那麼奇怪的是start
方法被調用的很好,但在該方法結束後,我已經建立了連接到回調方法,但它從來沒有。之後沒有進一步的隊列操作被執行。就好像它在啓動方法返回後掛起,並且不會調用任何URL連接的回調!
如果我的併發操作先放在隊列中,那麼它一切正常,異步回調工作,並在完成後執行後續操作。我根本聽不懂!
你可以在下面看到我的併發NSOperation的測試代碼,我非常肯定它是穩定的。
任何幫助將不勝感激!
主線程觀察:
我剛纔發現,如果同時操作是先在隊列中,則[start]
方法被稱爲主線程。但是,如果它不是第一個在隊列中(如果它是在併發或非併發之後),那麼在主線程上不會調用方法[start]
。這看起來很重要,因爲它符合我的問題模式。這可能是什麼原因?
併發的NSOperation代碼:
@interface ConcurrentOperation : NSOperation {
BOOL executing;
BOOL finished;
}
- (void)beginOperation;
- (void)completeOperation;
@end
@implementation ConcurrentOperation
- (void)beginOperation {
@try {
// Test async request
NSURLRequest *r = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com"]];
NSURLConnection *c = [[NSURLConnection alloc] initWithRequest:r delegate:self];
[r release];
} @catch(NSException * e) {
// Do not rethrow exceptions.
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Finished loading... %@", connection);
[self completeOperation];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Finished with error... %@", error);
[self completeOperation];
}
- (void)dealloc {
[super dealloc];
}
- (id)init {
if (self = [super init]) {
// Set Flags
executing = NO;
finished = NO;
}
return self;
}
- (void)start {
// Main thread? This seems to be an important point
NSLog(@"%@ on main thread", ([NSThread isMainThread] ? @"Is" : @"Not"));
// Check for cancellation
if ([self isCancelled]) {
[self completeOperation];
return;
}
// Executing
[self willChangeValueForKey:@"isExecuting"];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
// Begin
[self beginOperation];
}
// Complete Operation and Mark as Finished
- (void)completeOperation {
BOOL oldExecuting = executing;
BOOL oldFinished = finished;
if (oldExecuting) [self willChangeValueForKey:@"isExecuting"];
if (!oldFinished) [self willChangeValueForKey:@"isFinished"];
executing = NO;
finished = YES;
if (oldExecuting) [self didChangeValueForKey:@"isExecuting"];
if (!oldFinished) [self didChangeValueForKey:@"isFinished"];
}
// Operation State
- (BOOL)isConcurrent { return YES; }
- (BOOL)isExecuting { return executing; }
- (BOOL)isFinished { return finished; }
@end
排隊代碼
// Setup Queue
myQueue = [[NSOperationQueue alloc] init];
[myQueue setMaxConcurrentOperationCount:1];
// Non Concurrent Op
NonConcurrentOperation *op1 = [[NonConcurrentOperation alloc] init];
[myQueue addOperation:op1];
[op1 release];
// Concurrent Op
ConcurrentOperation *op2 = [[ConcurrentOperation alloc] init];
[myQueue addOperation:op2];
[op2 release];
我也有這個相同的問題。但在我的情況下,啓動方法有時候也不需要新添加的操作。隊列仍顯示狀態'正在運行'。所以上面的方法不能使用。你知道任何其他解決方案嗎?請幫忙.. – 2013-06-12 06:59:55