NSOperationQueue没有运行所有操作

时间:2013-04-15 15:44:59

标签: ios nsoperation nsoperationqueue

我使用NSOperationQueue执行并发下载并插入Core Data。

以下是代码,我正在使用

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次操作,队列未运行。有人能告诉我。出了什么问题。

2 个答案:

答案 0 :(得分:2)

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

试试这个:

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];

答案 1 :(得分:0)

问题可能在于您使用NSURLConnection sendSynchronousRequest。这几乎总是一个坏主意,因为它会阻塞,这意味着,它可以使你的代码完全停止(听起来就像正在发生的事情)。

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