2012-11-19 67 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它可能是你手动管理交易,并以某种方式交易可能无法完成自己? –