【发布时间】:2015-08-26 17:39:44
【问题描述】:
以下代码是不安全的(或者至少我认为是):
using (SQLiteConnection connection = new SQLiteConnection("path")) {
MyTableCreationHelper.CreateTable(connection, "tableName"));
}
问题是如果另一个线程试图在不同的连接上创建一个到同一路径的表,数据库将被锁定,因此会抛出异常。为了防止这种情况,我可以执行以下操作:
object lockObject = myLockHelper.GetUniqueObjectForLocking("path"); //does what it claims to do; implementation not shown
lock (lockObject) {
using (SQLiteConnection connection = new SQLiteConnection("path")) {
MyTableCreationHelper.CreateTable(connection, "tableName"));
}
}
现在代码是安全的,但也更笨重,因为我每次都必须将 using 包装在锁中。我的问题是,有没有办法将 using 和 lock 结合起来让它不那么笨重?
理想情况下,它会以一种不依赖于我们的内部操作涉及 SQLiteConnection 的方式来完成。换句话说,为 SQLiteConnection 写一个加锁包装器是一个不太理想的解决方案,因为如果下一次,我的锁不涉及 SQLite,问题会再次出现。
【问题讨论】:
-
我认为您应该在
using(var connection = new...){中编写一个try-catch,而不是锁定。尝试创建一个表,如果它抛出异常,您知道该表已经存在。更好的是使用If(tableExists)之类的东西向表中添加行,否则创建它。 -
你确定数据库会抛出不同的“tableName”吗?似乎很容易序列化。
-
它确实对我产生了影响。我不知道为什么——它被捕获在一个不再明显的通用级别。
-
不是表存在的问题。异常说“数据库被锁定”,这一定意味着另一个线程正在访问它。考虑到我当时的所作所为,那会发生是有道理的。
-
不确定这里的锁定是否足够。 CreateTable 需要独占访问,同时从另一个线程查询/更新 Db 是否有效?
标签: c# multithreading using locks