C# 具有多线程访问的SQLitePCLRaw.provider.e_sqlite3.dll中的System.AccessViolationException或System.ExecutionEngineeException崩溃

C# 具有多线程访问的SQLitePCLRaw.provider.e_sqlite3.dll中的System.AccessViolationException或System.ExecutionEngineeException崩溃,c#,multithreading,sqlite,xamarin.forms,entity-framework-core,C#,Multithreading,Sqlite,Xamarin.forms,Entity Framework Core,编辑:(由数字6解决) 当多个线程同时访问myFoodContext时,是什么导致SQLitePCLRaw.provider.e_sqlite3.dll中的System.AccessViolationException或System.ExecutionEngineeException崩溃 我有一个Xamarin表单应用程序(3.5.0.169047),支持UWP、Android和iOS,使用NETstandard 2.0.3、Microsoft.EntityFrameworkCore 2.2.4

编辑:(由数字6解决)

当多个线程同时访问my
FoodContext
时,是什么导致SQLitePCLRaw.provider.e_sqlite3.dll中的
System.AccessViolationException
System.ExecutionEngineeException
崩溃

我有一个Xamarin表单应用程序(3.5.0.169047),支持UWP、Android和iOS,使用NETstandard 2.0.3、Microsoft.EntityFrameworkCore 2.2.4、Microsoft.EntityFrameworkCore.Sqlite 2.2.4,我有一个可重现的崩溃情况(在UWP上肯定会发生)我无法解决在同时从两个不同线程访问设备上的sqlite数据库时出现的问题。我有一个同步过程(将本地数据推送到API,并从API中提取在线数据),这可能需要一分钟左右的时间,因此我需要在单独的线程中执行,以使UI在运行期间保持响应。我还需要允许在同步期间查询本地数据,以允许在同步期间导航或在同步期间在应用程序内执行其他只读数据操作。如果我在同步过程中没有执行任何数据访问操作,那么长时间运行的同步可以正常工作,但在任何中断较短的数据访问操作完成后立即崩溃

从Visual Studio 2017(v15.9.5)的调试输出中可以看出,发生的两个崩溃异常(可能与导致相同复制品崩溃的时间相关)如下所示:

  • SQLitePCLRaw.provider.e_sqlite3.dll中发生类型为“System.AccessViolationException”的未处理异常 试图读取或写入受保护的内存。这通常表示其他内存已损坏

  • SQLitePCLRaw.provider.e_sqlite3.dll中发生类型为“System.ExecutionEngineeException”的未处理异常

  • 调试时,没有关于异常的其他详细信息;它发生在同步代码的不同长时间运行行中,具体取决于执行中断操作的时间;调试器显示发生异常的长时间运行的代码都包含在
    Try{…}捕获(异常){…}
    Try我的代码中的块

    这可能是什么原因造成的,如何解决

    我经历了以下所有过程:

  • SQLite的使用是否与多个线程兼容

    • 对,;根据和,默认情况下它处于“序列化”模式,支持无限制的多线程使用。正在使用的SQLite的底层版本是3.26.0,这是我在调试时调查我的
      Microsoft.Data.SQLite.SQLiteConnection
      信息时确定的
  • 是因为我不能同时打开多个具有写功能的连接吗

    • 没有;我甚至使用
      Microsoft.Data.Sqlite.SqliteConnectionStringBuilder
      修改了我的连接字符串,使其具有适当的
      模式
      SqliteOpenMode.ReadOnly
      SqliteOpenMode.ReadWriteCreate
      ),这取决于每次数据访问的需要
  • 是因为中断线程的
    FooDbContext
    Dispose()
    摆脱了长时间运行线程的
    FooDbContext
    所依赖的资源吗

    • 没有;我对此进行了大量调查,因为这是崩溃前我能击中的最后一个断点。即使我在
      FooDbContext
      中重写
      Dispose
      方法而不执行任何操作,甚至没有调用基类的
      Dispose
      (不推荐,但我暂时尝试过),崩溃仍然发生
  • 是否可以使用
    Microsoft.Data.Sqlite.SqliteConnectionStringBuilder
    Microsoft.Data.Sqlite.SQLiteConnection
    Microsoft.EntityFrameworkCore.DbContextOptionsBuilder
    使用Sqlite
    函数设置,以确保使用序列化模式(此时我不是100%确定)?

    • 没有;我仔细研究了一下,该选项必须隐藏在所选SQLite库的内部
  • 我做了大量的阅读和研究,但仍然没有给我什么可以尝试的东西

  • 编辑:为我解决此问题的答案:

  • 我注意到异常来自的dll是SQLitePCLRaw.provider.e_sqlite3.dll。这让我了解了到底是什么设置了低级SQLite库,最终是调用
    SQLitePCL.batters_V2.Init()。这可能是错误的吗?
    
    • 对,;事实证明,在阅读wiki信息之后,对
      SQLitePCL.batters\u V2.Init
      的调用在每个平台上只执行一次(在特定于平台的代码中,或在共享代码中,只要共享项目以及每个特定于平台的项目中安装了Microsoft.EntityFrameworkCore.Sqlite
    ).My
    SQLitePCL.batters.Init在
    FooDbContext
    中的
    onconfiguration
    中使用不正确,这使得它在每次配置
    FooDbContext
    时调用一次,而不是每次启动应用程序时只调用一次。移动
    SQLitePCL.batters\u V2.Init()
    配置
    行出来,进入我共享项目中的
    App.xaml.cs
    构造函数,修复了它!中断线程的数据访问后,崩溃不再发生。
    我真的希望这能帮别人省去我试图弄清这一问题时所省去的巨大麻烦

  • 为我解决此问题的答案:

  • 我注意到dll是异常c