oysteinkrog / SQLite.Net-PCL

Simple, powerful, cross-platform SQLite client and ORM - Updated version with PCL support
MIT License
353 stars 162 forks source link

Crash when using parallel tasks #308

Open wegascee opened 8 years ago

wegascee commented 8 years ago

I'm using InsertAll to add some entries to a table. Thereby I'm testing how the database behaves if simultaneous tasks wants to write to it. I tested it on different plattforms and on iOS and Android I get a crash. On UWP it seems to work. I have set up a sample project so that you can reproduce the issue:

private SQLiteConnection db;

//
// This method is invoked when the application has loaded and is ready to run. In this 
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    // DB setup
    string filename = "test.db3";
    string logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Logs");
    Directory.CreateDirectory(logPath);
    string path = Path.Combine(logPath, filename);
    Console.WriteLine(path);

    var platform = new SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS();
    this.db = new SQLite.Net.SQLiteConnection(platform, path);

    this.db.CreateTable<TableEntry>();

    Parallel.Invoke(() => ExecuteTaskAAsync(), () => ExecuteTaskBAsync());

    return base.FinishedLaunching(app, options);
}

private void ExecuteTaskAAsync()
{
    for (int i = 0; i < 10; i++)
    {
        Task.Delay(1000).Wait();
        //System.Diagnostics.Debug.WriteLine("Task A: [{0}]", i);
        TableEntry entry = new TableEntry();
        entry.Message = "Task A: [" + i + "]";
        this.db.InsertAll(new List<TableEntry>() { entry });
    }
}

private void ExecuteTaskBAsync()
{
    for (int i = 0; i < 10; i++)
    {
        Task.Delay(1000).Wait();
        //System.Diagnostics.Debug.WriteLine("Task B: [{0}]", i + 1);
        TableEntry entry = new TableEntry();
        entry.Message = "Task B: [" + i + "]";
        this.db.InsertAll(new List<TableEntry>() { entry });
    }
}

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

    public string Message { get; set; }

    public TableEntry() { }

    public TableEntry(string message)
    {
        Message = message;
    }
}

The debug output and the crash logs differs and doesn't contain any useful information for me. Also the test project gets different errors then my "real" project, but it always crashes. Attached you will find the test project (I left out the packages folder, because it takes too much space).