Vahid Amiri
Vahid Amiri

Reputation: 11117

What's the difference between these two async methods?

So I'm learning about async/await in C#, I made a small Windows forms app to just play with async/await. I came up with these:

Here is the button1_Click that's used for the two methods below:

    private void button1_Click(object sender, EventArgs e)
    {
        GetSiteAsync();
    }

and here is the look of the app:

enter image description here

Method 1:

    public async void GetSiteAsync()
    {
        HttpClient ht = new HttpClient();
        Task<string> getTaskString = ht.GetStringAsync("http://stackoverflow.com");

        label1.Text = "Loading...";

        string siteString = await getTaskString;

        label1.Text = "Finished! Site Length = " + siteString.Length;
    }

Method 2:

public async void GetSiteAsync()
{
    HttpClient ht = new HttpClient();
    string siteString = await ht.GetStringAsync("http://stackoverflow.com");

    label1.Text = "Loading...";

    label1.Text = "Finished! Site Length = " + siteString.Length;
}

In the first method when i click on 'Load URL' button, it changes the label to 'Waiting...' and when loading is finished it changes it to 'Finished!' with the site length appended to it.

In the second method when I click on the button it doesn't change the label and when operation is completed it changes the label to the site length.

I noticed that both methods don't cause the program GUI to freez while loading the website.

So Why does second method fail to change the button to 'Loading...'??

Upvotes: 2

Views: 82

Answers (3)

Servy
Servy

Reputation: 203819

In the first method you set the label test to loading and then await the task.

In the second method you await the task (meaning you don't continue executing the rest of the code in the method until it's already done) and then you set the label to loading (and then set it to done immediately afterward).

The methods don't block the UI thread because they're asynchronous; they return control to the calling code very quickly, and continue to do work after yielding control.

Upvotes: 1

Christos
Christos

Reputation: 53958

The code after an await operator is executed after the call in the await have been completed. This may be done in another thread. In the background a state machine is created and we say that the code after the await would be executed in a continuation.

So in the first case,

Task<string> getTaskString = ht.GetStringAsync("http://stackoverflow.com");
label1.Text = "Loading...";

You just make an asynchronous call and then you set the Text value of the label1.

While in the second case,

string siteString = await ht.GetStringAsync("http://stackoverflow.com");
label1.Text = "Loading...";

you await this call. This means that after the completion of this asynchrnous call, the setter of the label1.Text would be executed.

Upvotes: 3

dashnick
dashnick

Reputation: 2060

The second method immediately jumps to the label1.Text = "Finished! Site Length = " + siteString.Length; line after the label1.Text = "Loading..."; line, so you never actually see it. The first method, you see it, because the await happens after.

So: First method: "loading" -> await -> "Finished!" Second method: await -> "loading" -> "Finished!"

The "loading" is immediately written over in the second method.

Upvotes: 2

Related Questions