var response = await httpClient.GetAsync("something");
var content = response.Content.ReadAsStringAsync();
return new AvailableViewingTimesMapper().Map(content.Result);
–
–
Your first example is the correct one. The second example does not yield during the asynchronous operation. Instead, by getting the value of the content.Result
property, you force the current thread to wait until the asynchronous operation has completed.
In addition, as commenter Scott Chamberlain points out, by blocking the current thread it is possible you could introduce the possibility of deadlock. That depends on the context, but a common scenario for await
is to use that statement in the UI thread, and the UI thread needs to remain responsive for a variety of needs, but including to be able to actually handle the completion of an awaited operation.
If you avoid the second pattern, i.e. retrieving the value of the Result
property from a Task
you don't know has completed, not only can you ensure efficient use of your threads, you can also ensure against this common deadlock trap.
–
–
The reason why ReadAsString
is an async
method is, that actually reading the data is an IO Operation. The content might just not be fully loaded even if you already have the http result. There are no additional threads or big loads of computing involved.
HttpClient.GetAsync
allows you to add a HttpCompletionOption
to have the GetAsync
only return once the whole HttpResult
has been loaded. In that case, HttpContent.ReadAsStringAsync
will complete synchronously (a so called fastpath) because the content is already there.
So you should definitely await it.
Also: As this is probably library code that does not depend on returning at the UI thread, you should add .ConfigureAwait(false)
to all awaited method calls.
–
–
–
–
–
Here is .NET source code for ReadAsStringAsync.
If you look deeper in LoadIntoBufferAsync() method, you will see this will keep reading buffer from HttpResponse and leads to a potential further network call. This means it is a good practice to use await instead of Result.
[__DynamicallyInvokable]
public Task<string> ReadAsStringAsync()
this.CheckDisposed();
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
HttpUtilities.ContinueWithStandard(this.LoadIntoBufferAsync(), (Action<Task>) (task =>
if (HttpUtilities.HandleFaultsAndCancelation<string>(task, tcs))
return;
if (this.bufferedContent.Length == 0L)
tcs.TrySetResult(string.Empty);
Encoding encoding1 = (Encoding) null;
int index = -1;
byte[] buffer = this.bufferedContent.GetBuffer();
int dataLength = (int) this.bufferedContent.Length;
if (this.Headers.ContentType != null)
if (this.Headers.ContentType.CharSet != null)
encoding1 = Encoding.GetEncoding(this.Headers.ContentType.CharSet);
catch (ArgumentException ex)
tcs.TrySetException((Exception) new InvalidOperationException(SR.net_http_content_invalid_charset, (Exception) ex));
return;
if (encoding1 == null)
foreach (Encoding encoding2 in HttpContent.EncodingsWithBom)
byte[] preamble = encoding2.GetPreamble();
if (HttpContent.ByteArrayHasPrefix(buffer, dataLength, preamble))
encoding1 = encoding2;
index = preamble.Length;
break;
Encoding encoding3 = encoding1 ?? HttpContent.DefaultStringEncoding;
if (index == -1)
byte[] preamble = encoding3.GetPreamble();
index = !HttpContent.ByteArrayHasPrefix(buffer, dataLength, preamble) ? 0 : preamble.Length;
tcs.TrySetResult(encoding3.GetString(buffer, index, dataLength - index));
catch (Exception ex)
tcs.TrySetException(ex);
return tcs.Task;
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.