"Ожидание" не дожидается завершения вызова

Я создаю приложение Metro.

В MainPage.xaml.cs я создаю альбом следующим образом:

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.
}

Наконец, метод Initialize:

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" непосредственно с альбомом. Не имеет значения.

Есть ли быстрое решение этой проблемы? спасибо заранее.

Ответ 1

Да. Вся точка async и await заключается в том, что вы не блокируете. Вместо этого, если вы "ожидаете" операции, которая еще не завершена, продолжение запланировано для выполнения остальной части метода async, и управление возвращается вызывающему.

Теперь, поскольку ваш метод имеет тип 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, хотя вы можете добавить его для целей кеширования, если хотите.

Ответ 2

Сделайте Songs свойство return Task<List<Song>> и ждите в ListView1.ItemsSource = await album.Songs;