How to properly call SQLite functions from background thread on iPhone?

前端 未结 8 2011
礼貌的吻别
礼貌的吻别 2020-12-29 15:10

I\'m using an SQLite database in my iPhone app. At startup, there are some database actions that I want to perform in a separate thread. (I\'m doing this mainly to minimize

相关标签:
8条回答
  • 2020-12-29 15:59

    SQLite handles (sqlite3_stmt * for sure, and sqlite3 * I think) are thread-specific. The correct way to call them from multiple threads is to maintain a separate set of handles for each thread.

    0 讨论(0)
  • 2020-12-29 15:59

    I would use NSOperation and just do everything there during startup. NSOperation rocks. Did I say how much NSOperation rocks? It does. Rock, that is.

    0 讨论(0)
  • 2020-12-29 15:59

    If you are still not having any luck with above, you could try using this wrapper by EnormEGO https://github.com/jdp-global/egodatabase

    They use asynchronous callbacks which may kill two birds with one stone.

    Have a look at my Readme section for EGODatabaseRequest - asynchronous requests to db

    0 讨论(0)
  • 2020-12-29 16:01

    If you want to use SQLite on multiple threads with no restrictions, do the following before opening your connection:

    sqlite3_shutdown();
    sqlite3_config(SQLITE_CONFIG_SERIALIZED);
    sqlite3_initialize();

    http://www.sqlite.org/threadsafe.html

    0 讨论(0)
  • 2020-12-29 16:13

    My solution is to delete the app on my device (I want to delete the database that I created). This solves the problem for me.

    0 讨论(0)
  • 2020-12-29 16:14

    I've tried these two solutions and they worked perfectly. You can either use critical sections or NSOperationQueue and I prefer the first one, here is the code for both of them:

    define some class "DatabaseController" and add this code to its implementation:

    static NSString * DatabaseLock = nil;
    + (void)initialize {
        [super initialize];
        DatabaseLock = [[NSString alloc] initWithString:@"Database-Lock"];
    }
    + (NSString *)databaseLock {
        return DatabaseLock;
    }
    
    - (void)writeToDatabase1 {
        @synchronized ([DatabaseController databaseLock]) {
            // Code that writes to an sqlite3 database goes here...
        }
    }
    - (void)writeToDatabase2 {
        @synchronized ([DatabaseController databaseLock]) {
            // Code that writes to an sqlite3 database goes here...
        }
    }
    

    OR to use the NSOperationQueue you can use:

    static NSOperationQueue * DatabaseQueue = nil;
    + (void)initialize {
        [super initialize];
    
        DatabaseQueue = [[NSOperationQueue alloc] init];
        [DatabaseQueue setMaxConcurrentOperationCount:1];
    }
    + (NSOperationQueue *)databaseQueue {
        return DatabaseQueue;
    }
    
    - (void)writeToDatabase {
        NSInvocationOperation * operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(FUNCTION_THAT_WRITES_TO_DATABASE) object:nil];
        [operation setQueuePriority:NSOperationQueuePriorityHigh];
        [[DatabaseController databaseQueue] addOperations:[NSArray arrayWithObject:operation] waitUntilFinished:YES];
        [operation release];
    }
    

    these two solutions block the current thread until the writing to database is finished which you may consider in most of the cases.

    0 讨论(0)
提交回复
热议问题