2012-11-19 108 views
2

我想在我的應用程序中使用WebService進行事件同步來執行自定義日曆。異步任務鎖數據庫

一切都很好(呃,不是真的)。

日曆活動,以獲得當月的所有活動,並存儲在數據庫中啓動一個AsyncTaskonPostExecute方法更新到每天適當標記的看法。當用戶獲取到日曆活動,然後迅速回到主活動幾次

我的問題來了,讓我們說,例如

Main Activity>Calendar Activity(按返回鍵)>Main Activity>Calendar Activity(按後退按鈕)> ...

此時活動凍結由於database lock has not been available for 30 sec.或應用崩潰由於一個SQLiteConstraintException: error code 19

編輯SQLiteConstraintException行爲不再發生

由於更新是在我的應用程序非常重要,我每次重新輸入日曆活動我刪除數據庫與服務器的新數據,即使重新進行填充時間強硬是一樣的,在這一點上是鎖定的地方。

EDIT

我已經改變Delete > Insert樣式: Update所有數據(設定flag列= 0)>Insert新數據(設定flag柱= 1)>Delete(其中flag柱= 0)

我已經試過this解決方案取消關於Activi的AsyncTask TY沒有成功

結束,我相信這個問題是我不完全明白我在做什麼,所以我失去了一些東西真的很重要(或基本)的過程。

任何幫助改善我的代碼或只是指着我正確的方向,將不勝感激。

在此先感謝!

EDIT

我的應用程序具有其Aplication是負責創建單個數據庫連接(getWriteableDatabase();)和這種獨特的連接如的可達槽方法。

+1

'SQLiteConstraintException'應該與數據庫鎖定問題無關。異常是你的代碼中的一個錯誤,比如在sqlite表中定義了'NOT NULL'的地方插入'null'。 http://stackoverflow.com/questions/9599809/does-yieldifcontendedsafely-lose-the-benefits-of-a-transaction可能是鎖問題的解決方案 – zapl

+0

@zapl你是對的,'SQLiteConstraintException'因爲另一個拋出問題並沒有涉及到這個問題。現在已經解決了。 謝謝! –

回答

0

主要活動>日曆活動(按返回鍵)>主要活動>日曆活動(按返回鍵)> ...

這很可能會創造&開始新AsyncTask每次你打開日曆。

如果您不明確取消它,每個AsyncTask仍將運行。

如果它們並行或序列化運行,它取決於您用來執行AsyncTask的Android版本/執行程序。 > = Honeycomb的默認行爲是串行執行。在中解釋執行的順序部分在AsyncTask documentation

如果您使用串行AsyncTask,您可以排隊幾個(舊)任務,並且執行最近的任務可能需要一段時間。在離開活動時取消任務可能是一個好主意。

您收到的警告database lock has not been available for 30 sec.表示您在一個線程中寫入並嘗試同時從另一個線程訪問數據庫。不知道這是否需要兩個並行寫入線程。

問題是沒有使用不同的SQLiteDatabase實例。如果你這樣做,我認爲你會得到錯誤,而不是那個警告,因爲Android無法檢查一些隨機的SQLiteDatabase對象是否對數據庫有寫入鎖定。

那麼你可以做什麼: 我假設你使用事務,因爲鎖定數據庫很長時間沒有事務幾乎是不可能的。

  • 將您的事務處理的大小限制到一定的數量,這樣就保證可以在其他線程之間使用數據庫。
  • 使用db.yieldIfContendedSafely()動態停止交易。這將檢查另一個線程是否想要訪問數據庫並暫時結束事務。缺點:它會提交更改並且不能回滾整個事務。
  • 實驗SQLiteDatabase#enableWriteAheadLogging() & beginTransactionNonExclusive()正如在提前寫日誌文檔中提到的那樣。它讀取像它可能允許多線程訪問沒有鎖定問題。我還沒有進一步調查,如果這有效,它有什麼副作用。
+0

這是解決問題的正確思路。 我有幾個排隊的'AsyncTask',因此阻塞了我的數據庫,直到所有的數據都完成了,這可能是很長的時間。 –

1

嘗試序列化訪問您的數據庫。 SQLiteDatabase的每個實例代表到SQLite DB的單獨鏈接。在單個SQLiteDatabase實例上執行的操作是序列化的,但是當您在多個線程中混淆了多個SQLiteDatabase實例時,您所描述的錯誤就會開始彈出。

您沒有發佈任何代碼,所以我只是假設您每次訪問AsyncTasks中的數據庫時都會獲得一個新的SQLiteDatabase實例(使用.getWriteableDatabase()/ .getReadableDatabase())。嘗試使用單個SQLiteDatabase實例並將其傳遞給任務。這樣你就可以序列化數據庫訪問並避免AsyncTask線程競爭數據庫鎖定。

+0

我編輯了我的問題添加了更多的信息,也許我現在有點更清楚我如何處理'SQLiteDatabase' 感謝您的回答! –

+0

檢查這個線程:http://stackoverflow.com/questions/8200509/android-database-is-locked-by-other-thread它可能是你手動管理交易,並以某種方式交易可能無法完成自己? –