The second snippet has no benefits, doesn't "save" any threads while allocating another task object and making debugging and exception handling harder by wrapping any exceptions in an AggregateException.
A task is a promise that something will produce some output in the future. That something may be :
- A background operation running on a threadpool thread
- A network/IO operation that doesn't run on any thread, waiting instead for the Network/IO driver to signal that the IO has finished.
- A timer that signals a task after an interval. No kind of execution here.
- A TaskCompletionSource that gets signalled after some time. No execution here either
HttpClient.GetAsync
, HttpClient.GetStringAsync
or Content.ReadAsStringAsync
are such IO operations.
await
doesn't make anything run asynchronously. It only awaits already executing tasks to complete without blocking.
Nothing is gained by using ContinueWith
the way the second snippet does. This code simply allocates another task to wrap the task returned by ReadAsStringAsync
. .Result
returns the original task.
Should that method fail though, .Result
will throw an AggregateException
containing the original exception - or is it an AggregateException containing an AggregateException containing the original? I don't want to find out. Might as well have used Unwrap()
. Finally, everything is still awaited.
The only difference is that the first snippet returns in the original synchronization context after each await. In a desktop application, that would be the UI. In many cases you want that - this allows you to update the UI with the response without any kind of marshalling. You can just write
var response = await client.GetAsync("www.someaddress.yo");
string content = await response.Content.ReadAsStringAsync();
textBox1.Text=content;
In other cases you may not want that, eg a library writer doesn't want the library to affect the client application. That's where ConfigureAwait(false)
comes in :
var response = await client.GetAsync("www.someaddress.yo").ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);