iphone - SQLite 和 iPhone SDK 的线程

标签 iphone multithreading sqlite

我有一个 iPhone 应用程序,它使用 sqlite 3.6(不使用 FMDB)来存储和加载数据。我在应用程序加载时加载数据库,并在整个应用程序中使用相同的数据库连接。

在后台线程中,应用程序从网络服务器下载一些数据并写入数据库。同时主线程也可能需要写入同一个数据库。这有时会导致 EXC_BAD_ACCESS,因为两个线程都试图访问数据库。

从不同线程使用数据库的最佳和最简单的方法是什么?

这是一个显示问题的示例:

sqlite3 *database;   

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {   

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"database.db"];

    if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        return YES;
    }

    [NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];
    [self test];
    return YES;
}

-(void)test {
    for (int i = 0; i < 2000; i++) {
        NSLog(@"%i",i);
        sqlite3_exec([self getDb],"UPDATE mytable SET test=''", 0, 0, 0);
    }
}

编辑:

在 willcodejavaforfood 下面的回答之后,我尝试更改我的代码,为每个单独的线程使用单独的数据库对象(连接),并且还添加了 sqlite3_busy_timeout() ,以便在数据库繁忙时 sqlite 将重试写入。现在我不再得到 EXC_BAD_ACCESS 但我注意到并非所有数据都被插入。所以这也不是一个稳定的解决方案。让 sqlite 与线程一起工作似乎真的很难..

我的新解决方案具有单独的连接:

-(void)test {
    sqlite3 *db = [self getNewDb];
    for (int i = 0; i < 2000; i++) {
        NSLog(@"%i",i);
        sqlite3_exec(db,"UPDATE mytable SET test=''", 0, 0, 0);
    }
}

- (sqlite3 *)getNewDb {
    sqlite3 *newDb = nil;
    if (sqlite3_open([[self getDbPath] UTF8String], &newDb) == SQLITE_OK) {
        sqlite3_busy_timeout(newDb, 1000);
    } else {
        sqlite3_close(newDb);
    }
    return newDb;
}

最佳答案

我通过使用一个线程和一个 NSOperationQueue 来插入数据解决了这个问题。我会考虑一下。我从来没有能够获得一个具有多线程的稳定系统,而且大多数写入并不那么重要,排队确实有帮助。

根据要求,更多信息:

我有一个 NSOperation 的子类,我用要存储的模型对象实例化它。 然后,这些操作被提交到在单独线程中运行的 NSOperationsQueue 扩展。这个自定义队列只是添加一个指向数据库实例的指针。执行操作时,它使用[NSOperationsQueue currentQueue]属性来访问队列和数据库。我故意使用非并发操作(maxOperations 设置为 1)
因此,一次仅连续执行一个查询(或更新),完全在后台执行。

显然,完成后您需要某种回调。

这可能不是我能找到的最快但最稳定和最干净的解决方案。

文档:
http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/
http://icodeblog.com/2010/03/04/iphone-coding-turbo-charging-your-apps-with-nsoperation/

关于iphone - SQLite 和 iPhone SDK 的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4338031/

相关文章:

database - android SQLite 与平面文件

python sqlite3插入表错误: cursor is not connected?

java - 如何在 SQLite android studio 中替换表

IOS:如何在 UIWebview 中加载本地文件,例如:.png、.doc、.pdf 等

ios - 为什么 autoFocusRangeRestriction 没有效果?

iPhone自定义浏览器应用程序以编程方式在主屏幕上创建 'Bookmark'

multithreading - 在Delphi中,OutputDebugString线程安全吗?

iphone - PhoneGap 事件未在 iPhone 上触发

c# - 关闭在 Windows 服务中等待计时器的线程

java - 多线程中如何传递上下文