2016-11-21 59 views
1

我似乎無法讓異步按我想要的方式工作。總的來說,我對此很不熟悉,但是我的研究讓我感到很開心。這是我的情況:我有一個XAML表單,我需要從Web服務中加載數據。我可以得到這些數據,沒問題。問題是我希望表單能夠加載我已經做過的「Please wait。Data loading ...」屏幕,但是直到查詢結束纔會加載,這可能需要10秒鐘,這是一種糟糕的用戶體驗。任何人都可以讓我知道我做錯了什麼嗎?使用異步加載背景中的表單數據 - 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線程。 – wdosanjos

+0

看來您可能正在尋找某種方式將數據分頁成較小的部分,以便您可以在完成時顯示這些「頁面」。這聽起來更像是客戶端中的異步,而不是控制器或服務中的異步。後端的異步方法不會受到影響,但它們不會解決問題。 – clarkitect

+0

無論您調用LoadData方法的方法如何,都需要將調用放入IsLoading = Visibility.Visible;他們在調用LoadData之後。等待將控制權返回給調用函數,直到等待命令完成 – GreatJobBob

回答

3

編譯器會告訴你這種方法到底有什麼問題。具體來說,您的GetWebApiInfo方法將同步運行,因爲您從不使用await

在這種情況下,您可以使用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開始。例如,不要以async來標記GetWebApiInfo;從實際的HTTP傳輸開始,並使用await進行調用。然後讓async/await從那裏增長。

您可能會發現我的NotifyTask<T> type有幫助;它允許您執行諸如顯示/隱藏具有數據綁定功能的繁忙指標。

+0

我在發佈此答案時意味着發表評論,但是我與其他項目有偏差。謝謝,斯蒂芬!這是一個很好的解決方案。我不得不鼓勵它被稱爲讓所有工作都能正常工作,但現在它工作得很好。謝謝! –