FMDB, GCD против NSOperationQueue

У меня есть много данных, которые мне нужно вставить в две таблицы для моей базы данных sqlite. Я хочу поставить эту работу на задний план. Мой поток в основном выглядит так: (псевдокод)

while (files in database are not parsed) {

if (fileType == type1) {
   parseType1;
   showProgress;
}
else {
   parseType2;
   showProgress;
}
}

Я получил самую последнюю версию FMDB и подумал, что смогу поставить свои данные в очередь следующим образом:

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self databasePath]];

BOOL oldshouldcachestatements = _db.shouldCacheStatements;
[_db setShouldCacheStatements:YES];
[_db beginTransaction];
NSString *insertQuery = [[NSString alloc] initWithFormat:@"INSERT INTO %@ values(null, ?, ?, ?, ?);", tableName];
[tableName release];

__block BOOL success;

// Parse each line by tabs
for (NSString *line in lines) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *fields = [line componentsSeparatedByString:@"\t"];

    // Need to check since some of the .txt files have an empty newline at the EOF.
    if ([fields count] == NUM_FIELDS) {
        NSNumber *start = [NSNumber numberWithInteger:[[fields objectAtIndex:1] integerValue]];
        NSNumber *end = [NSNumber numberWithInteger:[[fields objectAtIndex:2] integerValue]];
        NSNumber *length = [NSNumber numberWithInteger:([end integerValue] - [start integerValue])];

        NSArray *argArray = [[NSArray alloc] initWithObjects:ID, start, end, length, nil];

        [queue inDatabase:^(FMDatabase *db) {
            success = [_db executeUpdate:insertQuery withArgumentsInArray:argArray];
        }];

        [argArray release];

    }
    [pool drain];
}

Оба моих метода parseType выглядят так. Когда я запускаю его самостоятельно, я получаю сообщение об ошибке, что FMDatabase в настоящее время используется. Это потому, что мне нужно поставить оба в очередь одним и тем же методом, а не отдельными методами? Я также пробовал что-то вроде этого:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0) ^{
   parseType1;
});
dispatch_async(dispatch_get_main_queue, ^{
   update UI;
});

Но я получаю ту же проблему, что db в настоящее время используется. Правильно ли я использую FMDatabaseQueue? Или мне нужно сделать что-то по-другому? Если я использую здесь NSOperationQueue вместо GCD, это лучше? Спасибо!


person Crystal    schedule 24.07.2012    source источник
comment
Возможно, это просто опечатка, но в блоке вызова [queue inDatabase:] вы используете переменную '_db' (переменная-член?), а не 'db' (параметр). Это может быть причиной, по которой вы получаете ошибку, но я считаю, что это просто опечатка.   -  person Sebastian Hojas    schedule 25.07.2012
comment
При использовании очереди операций убедитесь, что она является последовательной в соответствии с README OR SUFFER. Плохие вещи могут случиться, когда вы пытаетесь использовать параллелизм SQL-доступа.   -  person CodaFi    schedule 04.01.2013