我有一个使用NSOperationQueue的应用程序。NSOperationQueue会随机暂停吗?
有时我注意到,即使我的代码从未调用setSuspended:方法,某些NSOperationQueues会“锁定”或随机进入“isSuspended”状态。
复制并且很难调试是不可能的,因为每当我将设备连接到Xcode进行调试时,应用程序就会重新加载,错误就会消失。
我在所有可能的地方添加了很多NSLogs,可能有问题,只需要使用应用程序几天,直到错误重新出现。查看设备系统日志,我发现[myOperationQueue operationCount]会增加,但队列中的操作将不会执行。
我还没有尝试过手动设置“setSuspended:NO”,但是真的有必要吗?
这可能是什么原因造成的?
这里是我的代码一点点
调用操作
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
[self.operationQueue setMaxConcurrentOperationCount:2];
self.sendOperationQueue = [[[NSOperationQueue alloc] init] autorelease];
[self.sendOperationQueue setMaxConcurrentOperationCount:2];
self.receiveOperationQueue = [[[NSOperationQueue alloc] init] autorelease];
[self.receiveOperationQueue setMaxConcurrentOperationCount:1];
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[operationQueue cancelAllOperations];
[sendOperationQueue cancelAllOperations];
[receiveOperationQueue cancelAllOperations];
[operationQueue release];
[sendOperationQueue release];
[receiveOperationQueue release];
}
- (IBAction)sendMessage
{
if(![chatInput.text isEqualToString:@""])
{
NSString *message = self.chatInput.text;
SendMessageOperation *sendMessageOperation = [[SendMessageOperation alloc] initWithMatchData:matchData andMessage:message resendWithKey:nil];
[self.sendOperationQueue addOperation:sendMessageOperation];
[sendMessageOperation release];
}
}
视图控制器的NSOperation子类SendMessageOperation
- (id)initWithMatchData:(MatchData*)data andMessage:(NSString*)messageString resendWithKey:(NSString*)resendKey
{
self = [super init];
if(self != nil)
{
if(data == nil || messageString == nil)
{
[self release];
return nil;
}
appDelegate = (YongoPalAppDelegate *) [[UIApplication sharedApplication] delegate];
context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];
[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChanges:) name:NSManagedObjectContextDidSaveNotification object:context];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeMainContextChanges:) name:NSManagedObjectContextDidSaveNotification object:appDelegate.managedObjectContext];
self.matchData = (MatchData*)[context objectWithID:[data objectID]];
matchNo = [[matchData valueForKey:@"matchNo"] intValue];
partnerNo = [[matchData valueForKey:@"partnerNo"] intValue];
self.message = messageString;
self.key = resendKey;
apiRequest = [[APIRequest alloc] init];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
self.matchData = nil;
self.message = nil;
self.key = nil;
[context release];
[apiRequest release];
[super dealloc];
}
- (void)start
{
if([self isCancelled] == YES)
{
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
else
{
[self willChangeValueForKey:@"isExecuting"];
executing = YES;
[self main];
[self didChangeValueForKey:@"isExecuting"];
}
}
- (void)main
{
@try
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
bool taskIsFinished = NO;
while(taskIsFinished == NO && [self isCancelled] == NO)
{
NSDictionary *requestData = nil;
if(key == nil)
{
requestData = [self sendMessage];
}
else
{
requestData = [self resendMessage];
}
NSDictionary *apiResult = nil;
if(requestData != nil)
{
apiResult = [self sendMessageToServer:requestData];
}
if(apiResult != nil)
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"shouldConfirmSentMessage" object:nil userInfo:apiResult];
}
taskIsFinished = YES;
}
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
finished = YES;
executing = NO;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];
[pool drain];
}
@catch (NSException *e)
{
NSLog(@"Exception %@", e);
}
}
- (BOOL)isConcurrent
{
return YES;
}
- (BOOL)isFinished
{
return finished;
}
- (BOOL)isExecuting
{
return executing;
}
- (void)mergeContextChanges:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"mergeChatDataChanges" object:nil userInfo:[notification userInfo]];
}
- (void)mergeMainContextChanges:(NSNotification *)notification
{
NSSet *updated = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
for(NSManagedObject *thing in updated)
{
[[context objectWithID:[thing objectID]] willAccessValueForKey:nil];
}
[context mergeChangesFromContextDidSaveNotification:notification];
}
也许不相关,但你给的NSOperation子类不需要并发;你可以避免压倒性的开始,isFinished,isExecuting并让NSOperation为你处理。 –
是的,不知道它是否相关,但谢谢你的提示。 –