2017-06-03 17 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(非同期でデフォルトで行われる)をキャプチャする場合にのみ、デッドロックが発生します。 Sync-Contextをキャプチャしないようにするためには、すべての待ち受け可能な呼び出しに対してConfigureAwait(false)を使用する必要があります。 Stephen Clearyのhttps://blog.stephencleary.com/2012/07/dont-block-on-async-code.htmlとasync/awaitに関する彼の他の記事 –

答えて

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 
} 

これを非同期呼び出しが可能な方法で使用します。

ページ/ビュー

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

AppearingイベントをサブスクライブすることができますOnAppearing仮想メソッドで

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

Likeして実際にもハンドラであなたの非同期コードを呼び出す

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; 
} 
関連する問題