使用async在后台加载表单数据 - MVVM

时间:2016-11-21 21:02:41

标签: c# wpf asynchronous mvvm

我似乎无法以我想要的方式工作。我一般都不熟悉它,但是我的研究让我了解了它。这是我的情况:我有一个XAML表单,我需要加载,需要来自Web服务的数据。我可以得到数据,没问题。问题是我希望表单加载"请等待。数据加载......"我做过的屏幕,但是在查询完成之前没有任何内容加载,这可能需要10秒,这是一个糟糕的用户体验。谁能让我知道我做错了什么?

在我的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;
    }

1 个答案:

答案 0 :(得分: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开始。例如,不要先用GetWebApiInfo标记async;从实际的HTTP传输开始,并使用await进行调用。然后让async / await从那里成长。

您可能会发现我的NotifyTask<T> type很有帮助;它允许您执行诸如使用数据绑定显示/隐藏繁忙指示符之类的操作。