28

我正在构建一个 Metro 应用程序。

在 MainPage.xaml.cs 中,我将 Album 实例化如下:

Album album = new Album(2012);  //With the album ID as its parameter.
ListView1.ItemsSource = album.Songs;

在 Album.cs 中,构造函数如下:

public Album(int ID)
{
    this.ID = ID;
    Initialize();  //Serves as a wrapper because I have to call httpClient.GetStreamAsync() and "async" doesn't work for the constructor.
}

最后,初始化方法:

private async void Initialize()
{
    //...some code...
    HttpClient cli = new HttpClient();
    Stream SourceStream = await HttpClient.GetStreamAsync("http://contoso.com");
    //...some code...
    this.Songs = Parse(SourceStream);
}

问题是当它运行到 GetStreamAsync 时,它会ListView1.ItemsSource = album.Songs直接将专辑.Songs 设为 null。

有什么快速解决这个问题的方法吗?

4

2 回答 2

41

是的。async和的全部意义await在于你不会阻塞。相反,如果您正在“等待”一个尚未完成的操作,则会安排一个延续来执行异步方法的其余部分,并将控制权返回给调用者。

现在因为你的方法有一个类型void,你甚至无法知道它什么时候完成 - 如果你返回Task(这不需要对方法的主体进行任何更改),你至少能够解决它已经结束。

目前还不清楚您的代码是什么样的,但从根本上说,您应该只在初始化完成ItemsSource 后尝试设置。您可能也应该将MainPage代码放在异步方法中,如下所示:

Album album = new Album(2012);
ListView1.ItemsSource = await album.GetSongsAsync();

您的GetSongs()电话将是:

private async Task<List<Song>> GetSongsAsync()
{
    //...some code...
    HttpClient cli = new HttpClient();
    Stream SourceStream = await HttpClient.GetStreamAsync("http://contoso.com");
    //...some code...
    return Parse(SourceStream);
}

这意味着Songs将不再是其Album自身的属性,尽管如果您愿意,您可以将其添加到缓存中。

于 2012-09-02T12:35:27.477 回答
5

使Songs财产归还Task<List<Song>>并等待ListView1.ItemsSource = await album.Songs;

于 2012-09-02T12:34:25.127 回答