2017-06-03 108 views
1

我正在使用SQLite-PCL和Xamarin.Android進行數據存儲。我正在異步使用它,因此正在經歷一個死鎖問題。SQLite-Net-PCL死鎖問題

執行包含在DataHandler類:

構造

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

初始化功能

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

最後,該鎖()函數的實現問題的答案在這裏:https://stackoverflow.com/a/44127898/3808312

當對象被創建,Initialize().Wait()被調用,在第一次調用CreateTableAsync()死鎖,不幸的是,我真的不能調試到庫中不接觸它的拆卸。我使用異步模式錯誤還是什麼?是的,我知道Wait()是同步的。這只是爲了保持與其他方法相同的格式。

+1

它只會在捕獲Sync-Context(這是通過async默認完成的)時纔會死鎖。您必須在所有等待調用中使用ConfigureAwait(false)來聲明您不想捕獲Sync-Context。閱讀Stephen Cleary的https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html以及他關於異步/等待的所有其他文章 –

回答

2

對於這樣的問題,頻繁模式是使用異步工廠方法創建受影響的類。

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 
} 

然後以允許異步調用的方式使用它。

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

就像在這裏您可以訂閱Appearing事件的頁面/視圖

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

,並呼籲在實際的異步代碼OnAppearing虛方法,甚至處理

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; 
}