iOS FMDB多线程操作失败

时间:2017-06-06 01:53:09

标签: ios xcode fmdb

是的,我尝试用fmdb在多线程中操作数据库。 我创建了一个计时器,用于在子线程中以1.5秒的间隔查询数据库。 同时,它可以通过删除,添加,编辑操作在主线程中操作数据库。 我发现如果查询正在运行,删除添加编辑操作可能会失败。比如说数据库已被锁定。 我不知道fmdb在多线程中是如何工作的,这是我的代码:

-(NSArray *)list{

NSString *path = [[PathHelper cachePath] stringByAppendingString:@"/MessagesCache.db"];
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
NSMutableArray *list = [NSMutableArray array];
[queue inDatabase:^(FMDatabase *db) {
    [db open];
    FMResultSet *set = [db executeQuery:@"SELECT * FROM t_messagesCache ORDER BY triggerTime ASC;"];

    while (set.next) {

        MXNIMMessageModel *message = [MXNIMMessageModel new];
        message.msgType = [set intForColumn:@"msgType"];
        message.uid = [set stringForColumn:@"uid"];
        message.msg = [set stringForColumn:@"msg"];
        message.nickname = [set stringForColumn:@"nickname"]; ;
        message.name = [set stringForColumn:@"name"];
        message.url = [set stringForColumn:@"url"];
        message.ext = [set stringForColumn:@"ext"];
        message.dur = [set intForColumn:@"dur"];
        message.w = [set intForColumn:@"w"];
        message.h = [set intForColumn:@"h"];
        message.size = [set intForColumn:@"size"];
        message.lastInterval = [set intForColumn:@"lastInterval"];
        message.md5 = [set stringForColumn:@"md5"];
        message.sort = [set intForColumn:@"sort"];
        message.triggerTime = [set stringForColumn:@"triggerTime"];
        message.teamId = [set stringForColumn:@"teamId"];

        [list addObject:message];

    }
    [db close];

}];
return list;

}

- (BOOL)deleteMessageModelByUid:(NSString *)uid

{

__block BOOL result;
NSString *path = [[PathHelper cachePath] stringByAppendingString:@"/MessagesCache.db"];
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
[queue inDatabase:^(FMDatabase *db) {
    [db open];
    result = [db executeUpdateWithFormat:@"DELETE FROM t_messagesCache WHERE uid = %@",uid];
    [db close];
}];

return result;

}

2 个答案:

答案 0 :(得分:0)

您可以使用GCD SERIAL QUEUE将所有FBMD操作保留在线程上。

首先,定义一个全局串行队列:

@interface ExampleClass 
@property(nonatomic,strong) dispatch_queue_t queue;
@end

@implementation ExampleClass
//......
- (dispatch_queue_t)queue {
    if (_queue != nil) {
        _queue = dispatch_queue_create("SERIAL_QUEUE", DISPATCH_QUEUE_SERIAL);
    }
    return _queue;
}
//......
@end

然后,在队列中运行FMDB,这将保留一个线程上的所有操作:

//For list
dispatch_async(self.queue, ^{
    //NSArray *list = [yourObjectForFMDB list];
    dispatch_async(dispatch_get_main_queue(), ^{
        //do UI operation with list
    });
});

//For deleting
dispatch_async(self.queue, ^{
    //[yourObjectForFMDB deleteMessageModelByUid:@"1"];
});

理论:dispatch_async将创建一个新线程来执行任务,SERIAL QUEUE确保只创建一个线程。

这里的ExampleClass可以是全局使用的单例。

答案 1 :(得分:0)

我们可以在数据库打开时执行任何操作。所以在fmdb中你不能做mutithread,因为对于每个查询fmdb首先打开db fire query& return 结果集然后再次关闭它。

如果你需要执行那么你可以让db打开这两个任务..