I recently read Stephen Cleary's post regarding possible deadlocks that occur when we call async code in synchronous methods here: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Regarding a slightly modified example here (all I added was a writeline code):
// My "library" method.
public static async Task<JObject> GetJsonAsync(Uri uri)
{
  Console.WriteLine("Before await");
  using (var client = new HttpClient())
  {
    var jsonString = await client.GetStringAsync(uri).ConfigureAwait(true);
    return JObject.Parse(jsonString);
  }
}
// My "top-level" method.
public void Button1_Click(...)
{
  var jsonTask = GetJsonAsync(...);
  textBox1.Text = jsonTask.Result;
}
His explanation is that the top-level method is blocking the UI thread waiting for GetJsonAsync to finish whereas GetJsonAsync is waiting for the UI thread to be freed so it can finish executing.
My question is, isn't GetJsonAsync already on the UI thread? Why would it need to wait for it to be freed? According to this post here calling async functions don't necessarily create another thread for the method to execute on. So how would it cause an issue with the UI thread if GetJsonAsync was executing on the UI thread the entire time? Like when Console.WriteLine() is executed where is this done, if not on the UI thread? I feel like I'm missing something here but don't know what.
Clarification: At which point does the execution leave the UI thread/context and need to return? There so much discussion about needing to return but never when it leaves the thread/context.
 
                        
I recommend reading my
asyncintro. In summary:Every asynchronous method begins executing synchronously. This code:
calls
GetJsonAsyncon the UI thread, and it does begin executing on the UI thread. It executesConsole.WriteLineon the UI thread,news up a client on the UI thread, and even callsGetStringAsyncon the UI thread. It gets a task back from that method, and thenawaits it (I'm ignoring theConfigureAwait(true)for simplicity).The
awaitis the point at which things may become asynchronous. The task isn't complete (i.e., the client hasn't received the string yet), soGetJsonAsyncreturns an incomplete task to its caller. ThenButton1_Clickblocks the UI thread, waiting for that task to complete (by calling.Result).So, the state is currently
GetJsonAsyncis no longer running on the UI thread. It is not actually "running" anywhere.Later, when that string result arrives, the task that was returned from
GetStringAsyncis completed, andGetJsonAsyncneeds to resume executing. It's not already on the UI thread; it's not anywhere at the moment. Since theawaitcaptured a UI context, it will attempt to resume on that context (on the UI thread).