for循环中的异步任务

时间:2014-03-30 19:23:29

标签: ios grand-central-dispatch dispatch-async

我有三种方法可以执行,如下所示:

+(void)method1{
    // Some code
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0; i<count; i++) {
            //getting object(x) from json
            [self method2:x];//trigger method2
        }
    });
}

+(void)method2:(NSString*)x{
// Some code
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0; i<count; i++) {
            //getting objects(y,z) from json
            //SAVE that object in SQLite database
            [self method3:y:z];//trigger method3
        }
    });
}

+(void)method3:(NSString*)y :(NSString*)z{
// Some code
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0; i<count; i++) {
            //getting object from json
            //SAVE that object in SQLite database
        }
    });
}

我拥有的总是数据库中的随机数据,而且并非所有数据都存储起来。 我的问题是如何组织这些异步任务以在数据库中获取正确的数据。 非常感谢你的帮助。

编辑:

+(void)getData:(NSString*)artist{

    LKDBHelper* globalHelper = [LKDBHelper getUsingLKDBHelper];

    NSMutableArray *arrayOfSongs=[[NSMutableArray alloc]init];
    artist = [artist stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    //DLog(@"artisttt %@",artist);

    NSString *url=[NSString stringWithFormat:@"%@?artist=%@", @"http://localhost/kalimat/get_kalimat.php",artist];

    url = [url stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];

    //NSLog(@"url %@",url);

    NSURL *urlChannels= [ NSURL URLWithString:url];


    NSURLRequest *request = [NSURLRequest requestWithURL:urlChannels];

    [LKDBHelper clearTableData:[Song class]];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSMutableArray *arrayOfJson=JSON;


            for (int i=0; i<[arrayOfJson count]; i++) {
                //DLog(@"artist songs loop");

                NSMutableDictionary *songDico=[arrayOfJson objectAtIndex:i];

                DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass: [Song class]];

                Song *song = [parser parseDictionary:songDico];
                song.artist=artist;




                [globalHelper insertToDB:song];

                [self getLyricsWhereArtist:artist andSong:song.song];
            }



        });

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response,
                NSError *error, id JSON) {
        DLog(@"Request Failure Because %@",[error userInfo]);
    }];


    [operation start];

}

1 个答案:

答案 0 :(得分:2)

如果有多个线程更新数据库,则可以为SQLite交互创建专用串行队列,并将所有数据库交互分派到该单个队列。这样,即使您有多个线程执行网络操作,您也可以将所有数据库更新分派到这个新的专用队列,它将完全消除所有数据库争用问题。您可能有数据库更新失败,因为您有多个线程尝试更新同一个数据库,其中一些可能会失败。

您怀疑数据库更新可能会无声地失败,这一点令人担忧。您是否可能没有检查所有的SQLite调用的返回码?检查返回代码每个 SQLite调用是非常关键的,如果失败,请查看sqlite3_errmsg(或者如果使用FMDB,lastErrorMessage)。如果你不这样做,你只是盲目地飞行。在这一点上你很幸运,这个问题很明显,但下次问题可能会更加微妙,而且你会在头发中追踪问题。

最后,由于您已经在使用AFNetworking,我还建议您考虑使用AFHTTPRequestManager。具体而言,不是自己构建URL,而是使用GET方法,传递params字典。您的stringByAddingPercentEncodingWithAllowedCharacters代码通常可以正常运行,但在某些情况下可能会失败(特别是,您的参数值包含+&的不太可能的情况。此外,如果您使用GET并将请求管理器的operationQueue.maxConcurrentOperationCount设置为合理的,例如4,您还将消除请求在慢速连接上不必要地超时的可能性。最重要的是,AFHTTPRequestManager会处理一些微妙的网络问题,但您当前的实施不会。