2016-11-21 10 views
1

私が望むように非同期に動作するようには思えません。私は一般的にそれにはほとんど慣れていませんが、私の研究は私にそれをもたらしました。ここに私の状況があります:私は、Webサービスからデータが必要なXAMLフォームをロードしています。データを取得できますが、問題はありません。問題は、フォームに「Please wait。Data loading ...」という画面が表示されるようにすることですが、クエリーが完了するまで何もロードされず、10秒かかる場合があります。誰でも私が間違っていることを教えてもらえますか?asyncを使用してバックグラウンドでフォームデータを読み込む - MVVM

私のViewModelのメインセクションでは、LoadData()を呼び出してボールをローリングさせます。

私も考えていました...私は本当にここで欲しいものですか?

public async void LoadData() 
    { 
     IsLoading = Visibility.Visible; 
     MonitorData downloadInfo = await GetWebApiInfo(); 
     try 
     { 
      AssignDataToControls(downloadInfo); 
      IsLoading = Visibility.Collapsed; 
      Console.WriteLine("Loaded successfully."); 
     } 
     catch (Exception e) 
     { 
      IsLoading = Visibility.Collapsed; 
      Console.WriteLine("Error: " + e); 
     } 
    } 

    private void AssignDataToControls(MonitorData mon) 
    { 
     MainPanel.Clear(); 
     mon.MainPanel.ToList().ForEach(x => MainPanel.Add(x)); 
     Information = mon.Information; 
     MonitorText = mon.MonitorText; 
     ProgressData = mon.progList; 
    } 

    public async Task<MonitorData> GetWebApiInfo() 
    { 
     main = new MonitorData(); 

     var url = "::::::::WEB API ADDRESS::::::::"; 
     var request = (HttpWebRequest)WebRequest.Create(url); 
     //Task<HttpWebRequest> req = await (HttpWebRequest)WebRequest.Create(url); 
     //HttpWebRequest request = await GetWebRequest(url); 
     WebResponse response = request.GetResponse(); 
     Stream dataStream = response.GetResponseStream(); 
     StreamReader reader = new StreamReader(dataStream, Encoding.Unicode); 
     string responseFromServer = reader.ReadToEnd(); 
     var deserializer = new JavaScriptSerializer(); 
     main = deserializer.Deserialize<MonitorData>(responseFromServer); 

     reader.Dispose(); 
     response.Dispose(); 
     return main; 
    } 
+0

[BackgroundWorker](https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx)が必要なので、Web呼び出しは別のスレッドで処理されます。あなたの場合の 'async'メソッドの問題は、コントロールをUIに戻してUIスレッドをブロックする前に' wait'する必要があることです。 – wdosanjos

+0

データを小さな部分に改ページして、ページが完成したときに表示できるようにする方法があるようです。これは、コントローラやサービスよりもクライアントの非同期によく似ています。バックエンドの非同期メソッドは害はありませんが、問題は解決しません。 – clarkitect

+0

LoadDataメソッドを呼び出すメソッドから、IsLoading = Visibility.Visibleへの呼び出しを行う必要があります。 LoadDataを呼び出した直後のものです。待っているコマンドが終了するまで、呼び出し関数に制御を返します。 – GreatJobBob

答えて

3

コンパイラは、そのアプローチの何が間違っているかを正確に教えてくれます。具体的には、awaitを使用していないため、GetWebApiInfoメソッドが同期して実行されます。

この場合、HttpClientを使用して非同期に情報をダウンロードできます。それはWebResponseとかで周りいじくるよりもはるかに簡単です:一般的に

private static readonly HttpClient _client = new HttpClient(); 
public async Task<MonitorData> GetWebApiInfo() 
{ 
    var url = "::::::::WEB API ADDRESS::::::::"; 
    string responseFromServer; 
    using (var dataStream = await _client.GetStreamAsync()) 
    using (var reader = new StreamReader(dataStream, Encoding.Unicode)) 
    responseFromServer = await reader.ReadToEndAsync(); 
    var deserializer = new JavaScriptSerializer(); 
    return deserializer.Deserialize<MonitorData>(responseFromServer); 
} 

、あなたは「何かの非同期を作る」にしたいとき、あなたは最低レベルAPIから開始する必要があります。たとえば、GetWebApiInfoasyncを付けて開始しないでください。実際のHTTP転送から始めてawaitと呼んでください。それから、async/awaitをそこから成長させてください。

私のNotifyTask<T> typeが役に立ちます。ビジー状態のインジケータの表示/非表示、データバインディングの設定などを行うことができます。

+0

あなたがこの回答を投稿したときに私はコメントするつもりでしたが、私は他のプロジェクトと横断してしまいました。ありがとう、スティーブン!これは素晴らしい解決策です。私はすべてのものを動作させるためにどのように呼び出されているのかを見直さなければならなかったが、今はうまくいく。ありがとう! –

関連する問題