Search code examples
c#asynchronouswebrequest

Why isn't WebRequest.GetResponseAsync() async?


As far as I know WebRequest.GetResponseAsync() can be awaited and is asynchonous. But when I look at its source code at https://referencesource.microsoft.com/#System/net/System/Net/WebRequest.cs,99a2a9c8ebc067dc it isn't defined with the "async" keyword.

I thought you cannot await a method that is not defined as "async"?


Solution

  • I thought you cannot await a method that is not defined as "async"?

    This is a kind of "shorthand" way of thinking about it that can be useful while initially learning async, but falls apart when you gain more knowledge about async/await. There are two concepts that are not quite right in this sentence.

    First, code cannot await a method. What actually happens is that the method is called, exactly like any other method. That method returns a value - an awaitable type - and it is that return value that is actually awaited. It's common for us to talk about "awaiting a method", but that's just shorthand for "calling a method and awaiting its return value", which is more accurate but too awkward for most conversation.

    Second, async is just one way to create an awaitable return value (which can then be awaited). There are several other ways as well. For example, Task<T>.Factory.FromAsync is commonly used if you have an API that uses the older APM asynchronous pattern, and you want to use it with await. In that case, you would normally write wrapper methods that return Task<T> and are implemented using Task<T>.Factory.FromAsync (without async). Another common approach is to use TaskCompletionSource<T>, which can create a Task<T> around any kind of logical "future event".

    To put it another way, async is an implementation detail. This concept is further enforced by the fact that interface methods can be declared as returning Task and awaited, but only method implementations can be declared with async.