2013-04-15 29 views
1

我正在使用NSOperationQueue执行并发下载并插入到Core Data中。NSOperationQueue未运行所有操作

以下是代码,我使用

if(nil==queue) 
{ 
    queue=[[NSOperationQueue alloc]init]; 
    [queue setMaxConcurrentOperationCount:5]; 
} 
for (FileDetailsEntity *entity in array) 
{ 
    InoFileDownloader *fileDownloader=[[InoFileDownloader alloc]initWithFileDetailsEntity:entity andDelegate:self]; 
    [queue addOperation:fileDownloader]; 
} 


//InoFiledownloader.m file 

- (void)mergeChanges:(NSNotification *)notification 
{ 
    appDelegate=(InoAppDelegate*)[[UIApplication sharedApplication]delegate]; 
    NSManagedObjectContext *mainContext = [appDelegate managedObjectContext]; 

// Merge changes into the main context on the main thread 
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
           withObject:notification 
          waitUntilDone:YES]; 
} 


-(void)start 
{ 
    @autoreleasepool { 


    [self willChangeValueForKey:@"isExecuting"]; 
    self.isExecuting = YES; 
    [self didChangeValueForKey:@"isExecuting"]; 

    appDelegate=(InoAppDelegate*)[[UIApplication sharedApplication]delegate]; 

    NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] init]; 
    [ctx setUndoManager:nil]; 
    [ctx setPersistentStoreCoordinator: [appDelegate persistentStoreCoordinator]]; 


    // Register context with the notification center 
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
    [nc addObserver:self 
      selector:@selector(mergeChanges:) 
       name:NSManagedObjectContextDidSaveNotification 
      object:ctx]; 

    NSDictionary *taskID=[[NSDictionary alloc]initWithObjectsAndKeys:fileDetaislsEntity.fileId,@"fileId",nil]; 

    NSArray *arry=[[NSArray alloc]initWithObjects:taskID, nil]; 

    NSMutableDictionary *jsonRequest=[NSMutableDictionary new]; 

    [jsonRequest setValue:arry forKey:@"fileId"]; 

    jsonWriter = [[SBJsonWriter alloc] init]; 

    if(self.isCancelled) 
     return; 

    NSString *jsonString = [jsonWriter stringWithObject:jsonRequest]; 

    NSData *postData = [jsonString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 
    NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]]; 

    if(self.isCancelled) 
     return; 


    NSURL *url = [NSURL URLWithString:@"http://192.168.4.247:8080/InnoApps/mobjobs/post/imageDownload"]; 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    [request setURL:url]; 
    [request setHTTPMethod:@"POST"]; 
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 

    if(self.isCancelled) 
     return; 

    [request setHTTPBody:postData]; 
    NSHTTPURLResponse* response; 
    NSError* error = nil; 

    // NSLog(@"File started to download for the file id %@",entity.fileId); 

    if(self.isCancelled) 
     return; 

    //Capturing server response 
    NSLog(@"started to download for file id--%@",fileDetaislsEntity.fileId); 
    NSData* result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 
    NSLog(@"finished downloading data for file id--%@",fileDetaislsEntity.fileId); 
    // if(request) 
    //  NSLog(@"File downloaded for the file id %@",entity.fileId); 

    if(self.isCancelled) 
     return; 

    SBJSON *jsonParser=[SBJSON new]; 

    NSString *jsonStr=[[NSString alloc]initWithData:result encoding:NSUTF8StringEncoding]; 


    // if(response.statusCode!=0) 
    NSDictionary *resultDic; 

    if([response statusCode]!=0) 
    { 
     resultDic= [jsonParser objectWithString:jsonStr]; 
    } 
    else 
    { 
     resultDic=nil; 
    } 

    // NSLog(@"resultDic---%@",resultDic); 

    NSMutableDictionary *imageDetails= [[resultDic objectForKey:@"image"] objectAtIndex:0]; 
    NSString *imageStr=[imageDetails objectForKey:@"imageBlob"]; 


    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription 
            entityForName:@"FileDetailsEntity" inManagedObjectContext:ctx]; 

    [fetchRequest setEntity:entity]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"taskId = %@ AND fileId=%@",fileDetaislsEntity.taskId,fileDetaislsEntity.fileId]; 

    [fetchRequest setPredicate:predicate]; 

    NSError *errorTmp=nil; 
    NSArray *fileDetailsArray= [ctx executeFetchRequest:fetchRequest error:&error]; 

    if(errorTmp) 
     NSLog(@"error in fetching filedetails array----%@",[errorTmp localizedDescription]); 
    for(FileDetailsEntity *entity in fileDetailsArray) 
    { 
     [entity setFileData:[imageStr dataUsingEncoding:NSUTF8StringEncoding]]; 
    } 




    if(self.isCancelled) 
     return; 

    NSError *errorForDataSaving; 

    if(![ctx save:&errorForDataSaving]) 
     NSLog(@"failed to save data after downloading image ---%@",[error localizedDescription]); 

    NSLog(@"data saved in db for file id--%@",fileDetaislsEntity.fileId); 

    if(self.isCancelled) 
     return; 


    [self willChangeValueForKey:@"isFinished"]; 
    [self willChangeValueForKey:@"isExecuting"]; 
    isExecuting = NO; 
    isFinished = YES; 
    [self didChangeValueForKey:@"isExecuting"]; 
    [self didChangeValueForKey:@"isFinished"]; 

    [(NSObject*)self.delegate performSelectorOnMainThread:@selector(didFinishDownloadingFileWithFileId:) withObject:fileDetaislsEntity.fileId waitUntilDone:NO]; 



} 

} 


-(BOOL)isConcurrent { return YES; } 

-(BOOL)isExecuting { return isExecuting; } 

-(BOOL)isFinished { return isFinished; } 

-(BOOL)isCancelled { return cancelled; } 

只有它运行后最多15个或20的操作,队列不运行。有人可以告诉我吗?出了什么问题。

+0

使用'if(queue == nil)' – filou

回答

0

的问题很可能是所使用NSURLConnection sendSynchronousRequest。这几乎总是一个坏主意,因为它阻塞了,这意味着它可以让你的代码完全停下来(这听起来像是发生了什么)。

人们通常使用NSURLConnection sendSynchronousRequest,因为他们害怕或不知道如何正确使用NSURLConnection,即异步。但正确使用并不困难,值得一做。

+0

Hi matt,非常感谢您的回答。将同步请求更改为异步修复了我的问题。 – Karthick

2

你应该暂停队列之前添加操作,并su到恢复后,你完成日常添加操作池队列...

尝试这样的:

if(nil==queue) 
{ 
    queue=[[NSOperationQueue alloc]init]; 
    [queue setMaxConcurrentOperationCount:5]; 
} 

[queue setSuspended:YES]; 

for (FileDetailsEntity *entity in array) 
{ 
    InoFileDownloader *fileDownloader=[[InoFileDownloader alloc]initWithFileDetailsEntity:entity andDelegate:self]; 
    [queue addOperation:fileDownloader]; 
} 

[queue setSuspended:NO]; 

也在合并改变方法改变标志waitUntillDone为FALSE这样的:

[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
          withObject:notification 
         waitUntilDone:FALSE];