Quote:
The Status property is set to 'RanToCompletion', but the IsCompleted is 'false'. Until I log it again, then it is true.
It's not really anything to do with the
WaitAsync
call; it's the
Console.WriteLine
call that's the problem.
If you
decompile the IL of your method[
^], you'll see:
ldstr "Done async action. response.IsCompleted: {0}, and status code is {1}, task status: {2}"
ldloc.1
callvirt instance bool [System.Runtime]System.Threading.Tasks.Task::get_IsCompleted()
box [System.Runtime]System.Boolean
ldloc.1
callvirt instance !0 class [System.Runtime]System.Threading.Tasks.Task`1<class [System.Net.Http]System.Net.Http.HttpResponseMessage>::get_Result()
callvirt instance valuetype [System.Net.Primitives]System.Net.HttpStatusCode [System.Net.Http]System.Net.Http.HttpResponseMessage::get_StatusCode()
box [System.Net.Primitives]System.Net.HttpStatusCode
ldloc.1
callvirt instance valuetype [System.Runtime]System.Threading.Tasks.TaskStatus [System.Runtime]System.Threading.Tasks.Task::get_Status()
box [System.Runtime]System.Threading.Tasks.TaskStatus
call void [System.Console]System.Console::WriteLine(string, object, object, object)
Converting that back to low-level C# gives:
string message = "Done async action. response.IsCompleted: {0}, and status code is {1}, task status: {2}";
object param1 = response.IsCompleted;
HttpResponseMessage httpResponse = response.Result;
object param2 = httpResponse.StatusCode;
object param2 = response.Status;
Console.WriteLine(message, param1, param2, param3);
As you can see, each property is accessed separately. Whilst each property access may be thread-safe, the state of the
Task
you're accessing can and will change between property accesses.
Also bear in mind that
the Task's Result
property[
^] blocks the current thread until the task has completed.
So if the original task hasn't completed within 500ms:
object param1 = response.IsCompleted;
HttpResponseMessage httpResponse = response.Result;
object param2 = httpResponse.StatusCode;
You can demonstrate that by changing the order of your message parameters. Try:
Console.WriteLine("Done async action. response.IsCompleted: {1}, and status code is {0}, task status: {2}", response.Result.StatusCode, response.IsCompleted, response.Status);
and:
Console.WriteLine("Done async action. response.IsCompleted: {0}, and status code is {2}, task status: {1}", response.IsCompleted, response.Status, response.Result.StatusCode);