0

I've a selector that updates my sqlite (FMDB framework) database fillTopXTraps. When I call the selector up updates 2 separate databases, it fails in 'DataBase' class (shortly -> 'db'). And I've this error:

The FMDatabase is currently in use.

multiple times.

I tried to call fillTopXTraps using:

[databaseQueue addOperation:invokeOperation];
[databaseQueue waitUntilAllOperationsAreFinished];

And I've an error 'database is locked' and:

[NSOperationQueue addOperations:waitUntilFinished:]: 1 (of 1) operation is finished, executing, or already in a queue, and cannot be enqueued

I tried using FMDatabaseQueue and still have an error 'database is locked' and '...currently in use.'.

How can I make sure fillTopXTraps will not continue if its already being processed and will know to wait until finished and then continue. Or maybe the problem is the database which is called from multiple thread apparently, how can I fix it?

Idan Moshe
  • 1,675
  • 4
  • 28
  • 65
  • Are you using multiple FMDatabaseQueues? You should only be using one per database. – ccgus Feb 05 '14 at 18:58
  • I'm using one FMDatabaseQueue for updates/insert/delete and FMDatabase for SELECT statements when I need to return some value. – Idan Moshe Feb 06 '14 at 04:04

1 Answers1

0

If you dispatch your updates through a serial queue, they will run in FIFO order:

-(void)serialize:(void (^)(void))task
{
    static dispatch_queue_t serialQueue = NULL;
    if (!serialQueue) { 
        serialQueue = dispatch_queue_create("com.your.serial.queue", DISPATCH_QUEUE_SERIAL);
    }
    dispatch_async(serialQueue, ^{
        dispatch_sync(dispatch_get_main_queue(), task);
    });
}

[self serialize:^{
    // database update
}];

Note that the task runs asynchronously, but once it is executing, it syncs to the main queue. I hope that's what you are looking for.

Jano
  • 62,815
  • 21
  • 164
  • 192