Perdi Estaquel
Perdi Estaquel

Reputation: 846

Does accessing the result of an async call make it synchronous?

I'm working with Http calls.

Once I get a response (HttpResponseMessage), I want to access its content as a string:

string responseContent = responseMessage.Content.ReadAsStringAsync().Result;

Now, ReadAsStringAsync() is async but accessing Result should definitely be synchronous.

I tested the code and am not sure of the following:

Upvotes: 1

Views: 510

Answers (1)

ProgrammingLlama
ProgrammingLlama

Reputation: 38880

This one is fairly easily answered by the docs:

Accessing the property's get accessor blocks the calling thread until the asynchronous operation is complete; it is equivalent to calling the Wait method.

Once the result of an operation is available, it is stored and is returned immediately on subsequent calls to the Result property. Note that, if an exception occurred during the operation of the task, or if the task has been cancelled, the Result property does not return a value. Instead, attempting to access the property value throws an AggregateException exception.

(Emphasis mine)

To answer your questions directly;

  • Will this always work? - Yes, so far as it can unless the task fails or is cancelled.
  • Why does it work? - Because the code waits for the task to complete before returning the result.
  • Shouldn't I get an exception when trying to access Result? - No, because it isn't a simple property. As the docs state, you might get an exception if the task fails, or is cancelled.

As @Camilo Terevinto notes, depending on the context you're using it in, this might not always work how you expect. It could cause a deadlock.

The reason is that if you're using it in a scenario where a context exists (e.g. UI context, ASP.NET request context, etc.) then the internal mechanics of it calling .Wait() can lead to a deadlock: it's waiting for a good time to insert the result into the current context, and at the same time the current context is blocking to wait for the result. You might want to take a look at Stephen Cleary's blog about this. You can scroll down to "What Causes the Deadlock" for more information. You can also look at this question.

Of course, the ideal solution is to use async/await as appropriate all the way up the chain.

Upvotes: 3

Related Questions