2017-05-27 2 views
0

私はsqlite3書き込み(挿入/更新/削除)操作を実行すると、私のアプリは時々EXC_BAD_ACCESSでクラッシュしました。iOS - マルチスレッドでsqlite3の書き込み操作を正しく実行するにはどうすればよいですか?

dispatch_queue_tを作成します。

dispatch_queue_create("example.testQueue", DISPATCH_QUEUE_CONCURRENT); 

-dealData: paramsarray:

- (BOOL)dealData:(NSString *)sql paramsarray:(NSArray *)params { 
    __block BOOL result = NO; 
    dispatch_sync(_dbQueue, ^{ 
     sqlite3_stmt *stmt = nil; 

     //prepare 
     int code = sqlite3_prepare_v2(self.sqlite, [sql UTF8String], -1, &stmt, NULL); 
     if (code != SQLITE_OK) { 
      NSLog(@"SQL error:%@, %@, %s", sql, params, sqlite3_errmsg((__bridge sqlite3 *)(self))); 
     } 
     else { 
      //bind 
      for (int i=0; i<params.count; i++) { 
       NSString *value = safeString([params objectAtIndex:i]); 
       sqlite3_bind_text(stmt, i+1, [value UTF8String], -1, SQLITE_TRANSIENT); 
      } 

      //step 
      if(sqlite3_step(stmt) == SQLITE_ERROR) { // crash at this line 
       NSLog(@"SQL step failed:%@", sql); 
      } 
      else { 
       sqlite3_finalize(stmt); 
       result = YES; 
      } 
     } 
    }); 
    return result; 
} 

これは、複数のスレッドで同時にデータを書き込むことによって、原因と思われます。私はこの問題をどう扱うべきか分かりません。

+0

あなたの完全なコードを表示してください! – Lion

答えて

1

このためにディスパッチキューを使用するという考えは正しいですが、並行キューを使用することはできません。コンカレントキューは並列ブロックを実行するためです。 DISPATCH_QUEUE_SERIALを使用してシリアルキューに切り替えてください。

もう1つの方法は、データベース接続を開いて直列化モードで実行するときに、自分自身で同期化に気をつけず、代わりにSQLITE_OPEN_FULLMUTEXフラグを渡すことです。

+0

'sqlite3_open'を' sqlite3_open_v2'に置き換え、 'SQLITE_OPEN_FULLMUTEX'フラグを渡しても問題ありません。 'dispatch_sync'オペレーションコードを削除する必要がありますか? – tomfriwel

+0

それは傷つくことはないので、もはや必要ではないにしても、それを残すことができます。 – Sven

関連する問題