2013-01-21 7 views
8

ViewModelのコンストラクタにデータをロードしたいのですが、WinRTの非同期性のために非同期メソッドを使用する必要があります。残念ながら、非同期メソッドを同期メソッドとして使用しようとしているので、非同期コンストラクタを使用することはできません。アプリケーションロード時にデータ(非同期)をロードする方がはるかに良い方法があると確信していますが、現時点では私の心は空白です。コンストラクタ内のWinRT非同期データロード

私は考えている行を使用してアプリケーションを修正する方法を探していますか、これをより適切な方法で永続的に修正する方法を探しています。

私が直面している問題を示すために、コードは非常にシンプルです(ViewModelが見付かりません)。

public sealed partial class MainPage : Page 
{ 

    public string Data { get; set; } 

    public DataService _dataService { get; set; } 

    public MainPage() 
    { 
     this.InitializeComponent(); 

     _dataService = new DataService(); 
     var t = _dataService.GetData(); 

     Data = t.Result; 
    } 

    /// <summary> 
    /// Invoked when this page is about to be displayed in a Frame. 
    /// </summary> 
    /// <param name="e">Event data that describes how this page was reached. The Parameter 
    /// property is typically used to configure the page.</param> 
    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
    } 


} 

public class DataService 
{ 
    public async Task<string> GetData() 
    { 
     //Force async 
     await Task.Delay(1); 

     return "Hello"; 
    } 
} 

種類よろしく

答えて

9

私はasync in constructorsについての最近のブログ記事を書きました。要するに

、私はasyncファクトリメソッド好む:

同期的に実行するために非同期メソッドを強制
public sealed class MyViewModel : INotifyPropertyChanged 
{ 
    private readonly DataService _service; 

    private MyViewModel(DataService service) 
    { 
    _service = service; 
    } 

    private async Task InitializeAsync() 
    { 
    var result = await _service.GetData(); // async initialization 

    Data = result; // update data-bound properties with the results 
    } 

    // Data triggers INotifyPropertyChanged on write 
    public string Data { get { ... } set { ... } } 

    public static async Task<MyViewModel> CreateAsync() 
    { 
    var ret = new MyViewModel(); 
    await ret.InitializeAsync(); 
    return ret; 
    } 
} 
2

は通常、デッドロックにつながるので、私はそれをお勧めしませんが。ビューモデルの場合は、通常、変更通知を PropertyChangedイベントでサポートしているため、すべてのデータをすぐに利用できるようにする必要はありません。実際にデータがハードコードされていない場合は、すぐにデータを表示することを期待してはならず、データがロードされている間に進捗インジケータを表示することをお勧めします。したがって...

あなたのコンストラクタでは、結果を待たずに(コンストラクタで待つことができないため)非初期化メソッドを呼び出し、すべてのデータが利用可能になったときに初期化メソッドで - プロパティ/これらのプロパティのPropertyChangedイベントを発生させ、可視性を制御するビューモデルプロパティを変更して進行状況インジケータを非表示にします。

+2

エラー処理を念頭に置いてください。 'async'初期化メソッドによって返された' Task'が決して観察されなければ、例外は静かに呑み込まれます。だから、あなたの 'InitializeAsync'に' try'/'catch'を持っているか、別のメソッドが結果を' await'していることを確認してください。 –

+0

もちろん。これは、コールがイニシャライザにあるか、または状態が悪化する可能性があるその他の方法に関係なく適用されます。 –

関連する問題