async, await and strange result

2019-09-02 17:36发布

问题:

I am writing application on WP 8.1. One of my method is parsing html and everything was ok. But I want to change coding to have polish characters. So I must to have Length properties to variable type byte[]. To make this possible I need to use await and changed my method on asnych.

public async void GetTimeTable(string href, int day)
{
    string htmlPage = string.Empty;
    using (var client = new HttpClient())
    {
        var response = await client.GetByteArrayAsync(URL);

        char[] decoded = new char[response.Length];
        for (int i = 0; i < response.Length; i++)
        {
            if (response[i] < 128)
                decoded[i] = (char)response[i];
            else if (response[i] < 0xA0)
                decoded[i] = '\0';
            else
                decoded[i] = (char)iso8859_2[response[i] - 0xA0];
        }
        htmlPage = new string(decoded);
    }

    // further code... and on the end::
    TimeTableCollection.Add(xxx);
} 

public ObservableCollection<Groups> TimeTableCollection { get; set; }

Method is calling from MainPage.xaml.cs

vm.GetTimeTable(navContext.HrefValue, pivot.SelectedIndex);
TimeTableViewOnPage.DataContext = vm.TimeTableCollection; 

And now is my question. Why vm.TimeTableCollection is null? When I don't use async and await everything is ok and vm.TimeTableCollection has x elements.

回答1:

And now is my question. Why vm.TimeTableCollection is null?

Because you're executing an async operation without awaiting it. Hence, the request may not be complete when you access your vm property in the next line.

You need to change your method signature to async Task and await it:

public async Task GetTimeTableAsync(string href, int day)
{
    string htmlPage = string.Empty;
    using (var client = new HttpClient())
    {
        var response = await client.GetByteArrayAsync(URL);

        char[] decoded = new char[response.Length];
        for (int i = 0; i < response.Length; i++)
        {
            if (response[i] < 128)
                decoded[i] = (char)response[i];
            else if (response[i] < 0xA0)
                decoded[i] = '\0';
            else
                decoded[i] = (char)iso8859_2[response[i] - 0xA0];
        }
        htmlPage = new string(decoded);
    }

    // further code... and on the end::
    TimeTableCollection.Add(xxx);
} 

and then:

await vm.GetTimeTableAsync(navContext.HrefValue, pivot.SelectedIndex);

This means your top calling method has to become async as well. This is usually the behavior when dealing with async methods, you need to go async all the way.

Note, to follow TPL guidelines, you should mark any async method with the Async postfix, Hence GetTimeTable should be GetTimeTableAsync



回答2:

You're not awaiting the result:

await vm.GetTimeTable(navContext.HrefValue, pivot.SelectedIndex);
TimeTableViewOnPage.DataContext = vm.TimeTableCollection; 

If you don't await an async method, the program will execute it, and continue to execute the following code without waiting for it to finish.