What happens when you expect a task to be returned?

I am experimenting with new asynchronous and pending keywords. I produced the following asynchronous function:

private async static Task<string> GetStringAsync(string pageAddress) { HttpClient client = new HttpClient(); return client.GetStringAsync(pageAddress); } 

I understand that I am returning a Task<String> and can expect a result from another method. This method works just fine. My question is what happens (under the hood) when I replace the second line of the above function with the following (note the introduction of the await keyword):

 return await client.GetStringAsync(pageAddress); 

The function behaves exactly the same! Remember that the function returns Task<String> not string . Is the await keyword here degenerate? Is the compiler just removing it from my code?

+4
source share
3 answers

As Eric Lippert noted, the first version will not compile; you need to remove the async or you will get a type error.

Here's a useful mental model regarding how the async and await keywords work with the return type:

  • Any T value returned by the async method is wrapped in Task<T> .
  • The await (which you can think of as an operator), when applied to Task<T> , will "expand" it, resulting in a value of type T

Now, what an extreme simplification; which is actually more complicated. For example, this simplification skips over how await works with the current SynchronizationContext : in the second example, the method will try to return to the original context after await completes, so you will see different behavior if this context is busy.

But for the most part, two examples are almost equivalent. The second one is less efficient due to the async state machine and context renewal.

I have an async / await intro that might be useful; in this article I am trying to explain async in such a way that it is not too complicated, but also not actually wrong. :)

+6
source

The answer to this question is too large to publish here your probable current level of understanding. What you need to do is start by reading my MSDN article and then the MSD Mads article. they are a good beginner introduction to this feature, and Mads describes how it is implemented. Here you can find the links:

http://blogs.msdn.com/b/ericlippert/archive/2011/10/03/async-articles.aspx

Then, if you are interested in the theory underlying this function, you should start by reading all of my articles on the style of continuing the passage:

http://blogs.msdn.com/b/ericlippert/archive/tags/continuation+passing+style/

Start from the bottom. When you understand the concept of continuation, you can read my series of articles on how we developed the asynchronous function:

http://blogs.msdn.com/b/ericlippert/archive/tags/async/

+7
source

Eric is obviously an expert here, and his advice sounds, but to answer your specific question:

In the first version, the async in the method does not matter, and your GetStringAsync method returns the same Task<string> that client.GetStringAsync will return.

In the second version, the async in the method is required because you are using await in the method, and the await keyword creates and returns a separate Task<string> , which ends after it has client.GetStringAsync completed. When this happens, await then evaluates the string that was received asynchronously with client.GetStringAsync , which is returned as a result of your asynchronous method.

So, for the calling GetStringAsync , they are functionally the same, but the first version is cleaner.

+2
source

Source: https://habr.com/ru/post/1490039/


All Articles