1

I am using SQLite-PCL with Xamarin.Android for data storage. I am using it asynchronously, and am experiencing a deadlock issue because of this.

The implementation is contained in a DataHandler class:

Constructor

public DataHandler(string path)
{
      _db = new SQLiteAsyncConnection(path);
      Initialize().Wait();
}

Initialize Function

private async Task Initialize()
{
    using (await Lock())
    {
        await _db.CreateTableAsync<Person>();
        await _db.CreateTableAsync<Animal>();
    }
 }

And lastly, that Lock() function is an implementation of the answer at the question here: https://stackoverflow.com/a/44127898/3808312

When the object is constructed, Initialize().Wait() is called and deadlocks on the first call to CreateTableAsync() and unfortunately, I can't really debug into the library without touching the disassembly of it. Am I using async pattern wrong or something? And yes, I do know that Wait() is synchronous. That was just to keep the same format as the other methods in the class.

1
  • 1
    It will only deadlock if you capture the Sync-Context (which is done by default with async). You must use ConfigureAwait( false ) on all awaitable calls to state you do not want to capture the Sync-Context. Read blog.stephencleary.com/2012/07/dont-block-on-async-code.html from Stephen Cleary and also all of his other articles about async/await Commented Jun 3, 2017 at 21:32

1 Answer 1

3

For issues like this, a frequent pattern is to create the affected class using an async factory method.

public class DataHandler {

    //...other code 

    private DataHandler() {

    }

    private async Task InitializeAsync(string path) {
        _db = new SQLiteAsyncConnection(path);
        using (await Lock()) {
            await _db.CreateTableAsync<Person>();
            await _db.CreateTableAsync<Animal>();
        }
    }

    public static async Task<DataHandler> CreateDataHandler(string path) {
        var handler = new DataHandler();
        await handler.InitializeAsync(path);
        return handler;
    }

    //...other code 
}

and then use it in a manner that allows async calls.

var handler = await DataHandler.CreateDataHandler("<path here>");

Like in the OnAppearing virtual method where you can subscribe to the Appearing event of the page/view

protected override void OnAppearing() {
    this.Appearing += Page_Appearing;
}

and call your async code on an actual even handler

private async void Page_Appearing(object sender, EventArgs e) {
    //...call async code here
    var handler = await DataHandler.CreateDataHandler("<path here>");
    //..do what you need to do with the handler.

    //unsubscribing from the event
    this.Appearing -= Page_Appearing;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.