c# - 在 Windows 8.1 (WinRT) 上调用 SQLite3.SetDirectory 会产生 System.AccessViolationException

标签 c# sqlite windows-8.1 sqlite-net

在我的 Windows 8.1 (WinRT) 应用程序中,我使用 SQLite v 3.8.9SQLite-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):

System.AccessViolationException

留言:

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/

相关文章:

c# - 平假名到汉字转换器

c# - 实体类型 'IdentityUserLogin<string>' 需要定义主键

java - 我无法使用 ORMLite 库在 java (android) 中执行 "WITH RECURSIVE"子句

c# - 在 Windows 8 XAML 中创建项目填充到控件宽度的水平列表?

windows - 从另一个 Windows 运行时应用程序检索数据

c# - 如何防止 Ace 在当前目录中寻找主题和模式?

c# - 创建新的 PayPal.Payments.DataObjects.TransactionResponse

java - SQLITE_ERROR SQL 错误或缺少数据库( "VALUES"附近 : syntax error)

sqlite3 JOIN,GROUP_CONCAT 使用不同的自定义分隔符

css - 如何防止图像在 Windows RT WebView 中变为 "draggable"