multithreading - sqlite and threading with iPhone SDK -
i have iphone app using sqlite 3.6 (not fmdb) store , load data. load database when app loads , uses same database connection through whole app.
in background thread app downloads data webserver , writes database. @ same time main thread might need write same database. leads exc_bad_access both threads trying access database.
what best , easiest way able use database different threads?
this example shows problem:
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 { (int = 0; < 2000; i++) { nslog(@"%i",i); sqlite3_exec([self getdb],"update mytable set test=''", 0, 0, 0); } }
edit:
after willcodejavaforfood's answer below i've tried change code use separate database object (connection) each separate thread , added sqlite3_busy_timeout() sqlite retry write if database busy. don't exc_bad_access anymore i've noticed not data inserted. not stable solution either. seems hard sqlite working threading..
my new solution separate connections:
-(void)test { sqlite3 *db = [self getnewdb]; (int = 0; < 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; }
i solved problem using 1 thread , nsoperationqueue
insert data. give thought. i've never been able stable system mutliple threads, , writes aren't important queuing helps.
as per request, more infos:
i have subclass of nsoperation
instantiate model object want store. these operations submitted extension of nsoperationsqueue runs in seperate thread. custom queue adds pointer database instance. when operation executed, uses [nsoperationsqueue currentqueue]
property access queue , database. on purpose, used non-concurrent operations (maxoperations set 1)
hence, 1 query (or update) executed @ time consecutivly, in background.
obviously need kind of callback after you're finished.
it possibly not fast, stable , cleanest solution find.
docs:
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/
Comments
Post a Comment