c#Xamarin SQLite.Net序列化模式无法正常工作?

时间:2018-04-19 22:31:07

标签: c# multithreading sqlite xamarin serialization

我在Android和iOS中使用库 SQLite.Net-PCL ,刚刚遇到错误。也许我误解了一些东西,但SQLite文档声明:

  

序列化即可。在序列化模式下,SQLite可以被多个安全使用   线程没有限制。

但是,当我通过多个线程共享连接时,似乎出现了问题。

我写了一个测试应用程序。见下文。

同时"同时"插入,我得 SQLite.Net.SQLiteException:误用

这是完整的例外:

  

SQLite.Net.SQLiteException:误用于   SQLite.Net.PreparedSqlLiteInsertCommand.ExecuteNonQuery   (System.Object [] source)[0x0016b] in   < 8f2bb39aeff94a30a8628064be9c7efe>:0 at   SQLite.Net.SQLiteConnection.Insert(System.Object obj,System.String   extra,System.Type objType)[0x000fc] in   < 8f2bb39aeff94a30a8628064be9c7efe>:0 at   SQLite.Net.SQLiteConnection.Insert(System.Object obj)[0x00012] in   < 8f2bb39aeff94a30a8628064be9c7efe>:0 at   test.TestTask +<> c__DisplayClass4_0.b__0(System.Object aName)   [0x00052]在/Users/dev/Documents/Xamarin/TestRepo/test/TestTask.cs:49

如果您之后查看数据库,它甚至看起来有重复的记录。

所以我的问题是:序列化模式是不是设计为在多个线程中使用单个连接?或者它是SQLite lib中的错误?

TestTask.cs(由Android和iOS共享):

using System;
using System.Threading.Tasks;
using SQLite.Net;
using SQLite.Net.Attributes;
using SQLite.Net.Interop;

namespace test
{
    [Table("test_class")]
    public class TestClass
    {
        [PrimaryKey, AutoIncrement, Column("_id")]
        public int Id { get; set; }

        [Column("caption")]
        public string Caption { get; set; }
    }

    public static class TestTask
    {
        static Task taskA;
        static Task taskB;

        public delegate void OnMessage(string msg);

        public static void Init(ISQLitePlatform platform, string path, OnMessage onMsg)
        {
            var con = new SQLiteConnection(platform, path);
            con.CreateTable<TestClass>();
            taskA = GetTask("First", con, onMsg);
            taskB = GetTask("Second", con, onMsg);
        }

        static Task GetTask(string name, SQLiteConnection connection, OnMessage onMsg)
        {
            return new Task((aName) =>
            {
                int i = 0;
                onMsg("Start " + aName);
                for (i = 0; i < 1000; i++)
                {
                    var obj = new TestClass
                    {
                        Caption = i + ": " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss:fff")
                    };

                    try
                    {
                        connection.Insert(obj);
                    }
                    catch (Exception e)
                    {
                        onMsg(aName + " -> " + "Index: " + i + " Error: " + e.Message);
                    }
                }
                onMsg("End " + aName);
            },name);
        }

        public static void Run()
        {
            taskA.Start();
            taskB.Start();
        }
    }
}

用法(iOS示例):

    void HandleOnMessage(string msg)
    {
        UIApplication.SharedApplication.InvokeOnMainThread(() => Console.WriteLine(msg));
    }

    void DoIt()
    {
        var platform = new SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS();
        platform.SQLiteApi.Config(ConfigOption.Serialized);

        var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        path = Path.Combine(path, "test.db");

        TestTask.Init(platform, path, HandleOnMessage);
        TestTask.Run();
    }

其他信息:

  • 我在Android模拟器和Android设备中遇到同样的问题
  • 我正在使用Visual Studio for Mac 7.4.3(Build 10)
  • 我在使用iOS 11.3的iPhoneX模拟器上进行调试

1 个答案:

答案 0 :(得分:2)

我自己解决了。

这是“SQLite.Net PCL”Nuget Package中的一个问题。

在Connection上使用“sqlite-net-pcl”代替Read | Write | FullMutex Flags。 FullMutex标志强制执行序列化模式。