Question

I'm having a deadlock in my program but I can't figure out why and how to fix it.

Short version:

An async to sync method locks waiting for an async call, which calls another, and so on until a HttpClient.PostAsync call. The http post call never happens, at least it doesn't arrives in the server (which I own too). No errors in the client. My main questions are at the end of this SO question. Thanks!

Longer version:

I know that it is very easy to come up with deadlocks and we must be careful. I'm trying to adhere to the advices of 1. Propagate the async down to all the methods and 2. Use ConfigureAwait(false) whenever possible/make sense. (I think the main advocate of this is Stephen Cleary as his blog and answers in many SO which I have read many of them).

Well, my program... I cannot post a full sample code here unfortunately, it's rather long; I describe it as a sync method A that calls an async method B, which calls another async, which calls another async, etc. Eventually the last async call is HttpClient.PostAsync.

Program stop's at the await HttpClient.PostAsync. Also, the Http post never fires (I own the target server and in this case it never receives a request). (I double checked the uri etc.).

As a result, the synchronous method locks waiting for B's async task to complete which never happens. A looks like this:

public Byte[] A()
{
var task = BAsync();
return task.GetAwaiter().GetResult();
}

I use synchronization this way as he method does not need the context back, and I saw the method suggested by Stephen in Nito is implemented using this. (I also tried task.Result instead with same results).

The code of the http post call is:

private static async Task<HttpResponseMessage> PostAsync(Uri serverUri, HttpContent httpContent)
{
var client = new HttpClient();
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
}

The app's UI freezes. It's a WP8 app. In this aspect, the buttons do not react to Click events but ScrollViews still work. This is topic for another question but I prefer to include this detail in the question.

I'm not even sure I have a deadlock, or maybe is a HttpClient bug? (I don't think so, the same method is working in other workflows in the same app).

I tried to verify for deadlock and used VS's threads debugger window but only the main thread seems to be active. I also tried with all other sort of debugger windows but nothing gave me a hint.

My main questions are:

  1. Am I having a deadlock?
  2. How can I verify, maybe using VS, that I do have a deadlock?
  3. Is it at Client.PostAsync? If yes why and how to fix it?
  4. If not, any ideas please.

Edit: Method A gets called using reflection with MethodInfo.Invoke. I believe now this is part of the problem.

Was it helpful?

Solution

I believe you are seeing a deadlock, though I'm not sure how to prove it.

HttpClient on most platforms properly uses ConfigureAwait(false) internally, but on a few platforms does not. I believe that WP8 is one of those that does not. This means that you can use ConfigureAwait(false) all you want correctly, but HttpClient can still cause a deadlock.

The best solution is to go async all the way. But if that's not possible, then two alternatives come to mind:

  1. Push the HttpClient work off to a background thread.

    public Byte[] A()
    {
      var task = Task.Run(() => BAsync());
      return task.GetAwaiter().GetResult();
    }
    
  2. Establish a nested loop on the foreground thread to execute any asynchronous work.

    public Byte[] A()
    {
      return AsyncContext.Run(() => BAsync());
    }
    

    Note that AsyncContext is from my AsyncEx library. I believe AsyncContext should work on WP8 but I haven't actually used it on that platform.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top