2017-04-12 11 views
2

プロパティに非同期データをロードする方が良い方法があるのだろうかと思います。今私は、非同期関数を作成し、このような財産の取得一部でタスクを上げる:MVVM c#非同期データをプロパティにロードする方法は?

private ObservableCollection<CProyecto> prope; 

public ObservableCollection<CProyecto> Prope 
{ 
    get 
    { 
     if (prope == null) 
     { 
      Task.Run(()=> LoadData()).Wait(); 
     } 

     return proyectos; 
    } 
    set 
    { 
     prope = value; 
     RaisePropertyChanged(); 
    } 
} 

async private Task LoadData() 
{ 
    Prope = await clsStaticClassDataLoader.GetDataFromWebService(); 
} 

をこのアプローチは動作しますが、それがあれば、画面がフリーズすることができますので、私は、.WAITの使用は好きではありませんサービスは速く応答しません。

この問題について私を案内してもらえますか?事前に

おかげで

+0

あなたはとにかく、呼び出し元のスレッドをブロックするのを待つ()メソッドを呼び出した場合、新しいタスクを開始するポイントは何... ..? – mm8

+0

非同期のプロパティについては、これをお読みください。https://blog.stephencleary.com/2013/01/async-oop-3-properties.html – mm8

+0

外部ソースからデータを取得するために 'loaded event'を使用してください。イベントを非同期にして、コレクションにバインドします。 – Eldho

答えて

1

方法は、プロパティをロードするプロセスを開始することでしたオブジェクトが構築されたときに、私は結果を待っていませんでした。プロパティが設定されたときにプロパティが通知するので、バインディングは正常に機能しました。基本的には次のように動作します。

これは非常にうまく動作し、UIに遅延や吃音を生じません。コレクションが決してnull(良い練習IMO)にならないようにするには、propeフィールドを空のコレクションで事前初期化することができます。

+2

これは良い最初のステップですが、 'LoadData'によってスローされたエラーを静かにスワップします。より包括的なアプローチでは、 'LoadData'にトップレベルの' try'/'catch'があり、エラー通知でUIを更新します。 –

+0

合意。私は私が取った_approach_を記述しています。ただし、エラー処理を行う正しい場所があります。 –

+0

コンストラクタから非同期メソッドを呼び出すことはできませんが、プロパティと同じ問題です。あなたはこの警告を受け取りました。https://msdn.microsoft.com/en-us/library/hh873131.aspx – KillemAll

0

Prope財産のあなたの現在の実装ではあまり意味がありません。 を呼び出すと主スレッドをブロックするので、バックグラウンドスレッドでLoadDataメソッドを実行するのは無意味です。あなたにもLoadData()メソッドによって返されたタスクに直接Wait()を呼ぶかもしれない:

//BAD IMPLEMENTATION! 
private ObservableCollection<CProyecto> prope; 
public ObservableCollection<CProyecto> Prope 
{ 
    get 
    { 
     if (prope == null) 
      LoadData().Wait(); 
     return proyectos; 
    } 
    set { prope = value; RaisePropertyChanged(); } 
} 

上記の実装はまだ悪いものです。プロパティのゲッターは、非同期操作を実行するものではありません。 https://blog.stephencleary.com/2013/01/async-oop-3-properties.html

...と彼のAsyncExライブラリに彼のNotifyTaskCompletionタイプに見て:あなたは、件名に@Stephenクリアリーのブログ投稿を読んでください、私はこれを取り扱わhttps://github.com/StephenCleary/AsyncEx

+0

それは感覚がないように見えますが、実際には感覚があります。もし私が私のWebサービスを呼び出すとシステムがハングアップしないならば。私はそれがサービスと呼ばれる方法のためだと思うvar Response = client.GetAsync(url).Result; – KillemAll

4

async MVVM data-bindingで私のMSDNの記事を読むことをお勧めします。私はそのように使用することができNotifyTask<T> typeを、提供a libraryを持っている:

public class MyClass : INotifyPropertyChanged 
{ 
    public NotifyTask<ObservableCollection<CProyecto>> Prope { get; private set; } 

    public MyClass() 
    { 
    // Synchronously *start* the operation. 
    Prope = NotifyTask.Create(LoadDataAsync()); 
    } 

    async private Task<ObservableCollection<CProyecto>> LoadDataAsync() 
    { 
    return await clsStaticClassDataLoader.GetDataFromWebService(); 
    } 
} 

次に、あなたのデータバインディングがPrope.Result上で動作します。

このアプローチの利点は、データが(Prope.IsSuccessfullyCompleted)利用可能で、エラー通知(Prope.IsFaulted/Prope.ErrorMessage)したときにも/ショー忙しい指標(Prope.IsNotCompleted)、ショーのコントロールを非表示にするデータバインディングを使用することができるということです。あなたが望むなら

また、あなたは、非nullデフォルト値を指定することができます。

Prope = NotifyTask.Create(LoadDataAsync(), new ObservableCollection<CProyecto>()); 
+0

私はそれを読むつもりです、ありがとうございます – KillemAll

関連する問題