在我的 Windows 8.1 (WinRT) 应用程序中,我使用 SQLite v 3.8.9与 SQLite-net作为我的数据库,SemaphoreSlim作为我的同步执行者。它通常有效,但有时当我尝试删除表条目时它会在 SQLite 的 C++ 代码中崩溃。
First-chance exception at (code) in (project name): Microsoft C++ exception: _com_error at memory location (location).
删除表格条目
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
时发生崩溃。
异常(exception):
留言:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
堆栈跟踪:
at SQLite.SQLite3.SetDirectory(UInt32 directoryType, String directoryPath)
at SQLite.SQLiteConnection..ctor(String databasePath, SQLiteOpenFlags openFlags, Boolean storeDateTimeAsTicks)
at SQLite.SQLiteConnection..ctor(String databasePath, Boolean storeDateTimeAsTicks)
问题
我猜这一定是线程问题,因为它通常可以正常工作并且有不规则的崩溃;但我找不到任何东西。
异常的原因是什么,我该如何解决?
我不认为它是损坏的内存,也许是 protected ,但我相当确定只有我的一个线程正在访问它
最佳答案
最后,尽管我确信一次只有一个线程访问 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 连接是打开的;即使他们正在访问不同的文件。
关于c# - 在 Windows 8.1 (WinRT) 上调用 SQLite3.SetDirectory 会产生 System.AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30056631/