我有一个在Sqlite3数据库上执行搜索的查询。除了使用阅读器阅读之外什么都不做。 对于每个找到的匹配,它会调用UI的回调来更新结果视图。
当此搜索正在运行时,我点击了UI中的一个按钮,该按钮将在新线程中执行其他操作。最后,它应该删除搜索控制器的视图并显示一个新的控制器。
但是,在某些时候触发的动作想要写入数据库。它只是挂起,最终我会看到数据库被锁定的异常。
有趣的是,搜索阅读器也没有继续,这是一个僵局。
我是否必须以某种特殊方式打开数据库以支持多线程使用?连接的构造函数是什么?
答案 0 :(得分:1)
MonoTouch 5.1+提供API,让您选择与SQLite一起使用的线程模型。
SqliteConnection.SetConfig (SQLiteConfig.MultiThread);
这映射到SQLite库的一些连接options。
更新:如果您使用的是早期版本的MonoTouch(例如介于4.2和5.0.x之间),您可以使用错误报告#652附带的二进制文件(按照说明操作) )或将补丁(p / invoke和enum)复制粘贴到您自己的应用程序中。
答案 1 :(得分:1)
我不确定我是否正确地解释了您的描述,但是您描述它的方式,听起来我的“读者”逐行遍历数据库,每次找到结果时都会进行回调回调函数?这是对的吗?
如果是这种情况,您可能会反复锁定数据库,搜索速度会很慢。
正确的方法是在一个查询中将所有匹配提取到结果集中 - 一旦完成该查询,将释放锁定,并且您从SQL中获得仅包含匹配行的结果集。
让SQLite通过使用“SELECT * FROM tablename WHERE columnX LIKE'%searchstring%'”
类型的查询来创建这样的结果集。(或类似的,取决于您的搜索条件)
这将创建一个包含数据库中所有匹配项的结果集,然后释放数据库锁。然后,您可以单步执行结果并创建对象并放入与UI视图相连的NSArray。
NSArray retval = [NSMutableArray array];
//Create a query
NSString *query = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ LIKE %@",
tableName, columnName, searchString];
sqlite3_stmt *statement;
//Database locks here
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
//Database should unlock here, the query is finished
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameChars = (char *) sqlite3_column_text(statement, 0);
NSString *name = [NSString stringWithUTF8String:nameChars];
SomeClass *info = [[SomeClass alloc] initWithName:name];
/* Extract other columns and put in your object */
[retval addObject:info];
[info release];
}
sqlite3_finalize(statement);
} else {
NSLog(@"SQL-statement failed");
}
这样做在必要时写入DB应该没有问题。仅在绝对必要时才对数据库执行新查询,例如,当您的搜索条件发生更改或数据库中的内容已更新时。
不要对未更改的数据库或未更改搜索条件的数据库运行重复查询。