在我的Windows 8.1(WinRT)应用程序中,我使用SQLite v 3.8.9作为数据库,而将SQLite-net作为同步执行器。它通常可以工作,但是当我尝试删除表条目时,有时会在SQLite的C ++代码中崩溃。
(项目名称)(代码)中的第一个机会异常:Microsoft C ++异常:内存位置(位置)处的_com_error。
删除表条目
private static SemaphoreSlim _mutex = new SemaphoreSlim(1,5);
public void DeleteItem(Item item)
{
_mutex.Wait();
using (var connection = new SQLiteConnection(Path))
{
connection.Delete(item);
}
_mutex.Release();
}
SQLite.cs
public SQLiteConnection (string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks = false)
{
...
#if NETFX_CORE
SQLite3.SetDirectory(/*temp directory type*/2, Windows.Storage.ApplicationData.Current.TemporaryFolder.Path);
#endif
...
}
当调用
SQLite3.SetDirectory
时发生崩溃。例外:
SemaphoreSlim
信息:
尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
堆栈跟踪:
在SQLite.SQLite3.SetDirectory(UInt32 directoryType,String directoryPath)
在SQLite.SQLiteConnection..ctor(字符串databasePath,SQLiteOpenFlags openFlags,布尔storeDateTimeAsTicks)
在SQLite.SQLiteConnection..ctor(字符串databasePath,布尔storeDateTimeAsTicks)
题
我猜想这一定是线程问题,因为它通常可以正常工作并且会出现不规则的崩溃;但我找不到任何东西。
导致异常的原因是什么,我该怎么办?
我不认为它是损坏的内存,也许是受保护的,但我可以肯定只有我的一个线程在访问它
最佳答案
最后,尽管我确信一次只有一个线程正在访问SQLite数据库,但事实证明,我有一些我没想到会同时被调用的次要代码。这导致AccessViolationException
为了确保将来不会出现此问题,我进行了以下操作:
为了将其隔离,将整个SQLite代码移至另一个项目。
在项目中实现半工厂模式,以确保只有一个线程使用它(这也使代码看起来更好)
工厂数据库类
public class DataBaseConnection: SQLite.SQLiteConnection
{
private const string _path = "MySQlitePath";
private static SemaphoreSlim _contextMutex = new SemaphoreSlim(1, 5);
private DataBaseConnection() : base(_path)
{
}
public static DataBaseConnection CreateDataBaseConnection()
{
_contextMutex.Wait();
return new DataBaseConnection();
}
private bool disposed = false;
protected override void Dispose(bool disposing)
{
if (disposed)
return;
if(disposing)
{
}
disposed = true;
base.Dispose(disposing);
_contextMutex.Release();
}
}
使用工厂
using (var connection = DataBaseConnection.CreateDataBaseConnection())
{
connection.Delete(item);
}
自从使用它以来,我再也没有见过
AccessViolationException
。使用多个数据库连接
如果您正在使用多个连接(即不同的数据库路径),例如:
MySQlitePath_1
MySQlitePath_2
...
MySQlitePath_N
您应该始终使用相同的同步机制(在我的情况下为
SemaphoreSlim
),以确保在任何给定时间仅打开一个SQLite连接。即使他们正在访问其他文件。