2

I'm working on an async http call using HttpClient. The call is made inside an async task. The call is successful and I get a response from the Http call. But when I try to return the response from the task nothing happens, even though I have a breakpoint waiting after the return.

public void ExecuteTask(Foundation.Security.SecurityToken token, Order order)
{
    ExecuteTaskAsync(token, order).Wait();
}

public async Task ExecuteTaskAsync(Foundation.Security.SecurityToken token, Order order)
{
    if (order != null)
    {
        log.Info("Starting export of order " + order.ID.ToString());
        bool success = await ExportOrder(order, token);
        if (!success)
        {
            log.Error("Failed to export order with ID " + order.ID.ToString());
        }
    }
}

private async Task<bool> ExportOrder(Order order, Foundation.Security.SecurityToken token)
{
    try
    {
        ResponseObject response = await webService.SendOrder(new SenderInformation(token), new ReceiverInformation(order, token));
        if (response.Success && response.Status.Equals("201", StringComparison.OrdinalIgnoreCase))
        {
            log.Info(String.Format("Order ({0}) was successfully exported"), order.ExternalOrderID);
           return true;
    }
        return false;
    }
    catch (Exception e)
    {
        log.Error(String.Format("Exception occured while exporting order ({0})", order.ID), e);
        return false;
    }
}

Below is the code which does the actual http call. I marked the last functional line with the comment "The code successfully reach this line. After this nothing happens"

public Task<ResponseObject> SendOrder(SenderInformation sender, ReceiverInformation receiver)
{
    OrderRequest request = new OrderRequest(sender, receiver);
    return ExecuteRequest<OrderRequest, ResponseObject>(request);
}

private async Task<ResponseType> ExecuteRequest<RequestType, ResponseType>   (RequestType request)
where RequestType : RequestObject
where ResponseType : class, ResponseObject, new() 
{
    try
    {
        using (var client = new HttpClient())
        {
            string xml = SerializeRequest(request);
            HttpContent content = new StringContent(xml);
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/xml");
            string requestUrl = "URL";
            HttpResponseMessage response = await client.PostAsync(requestUrl, content).ConfigureAwait(false);

            // Parse response
            if (response.IsSuccessStatusCode)
            {
                Stream responseStream = await response.Content.ReadAsStreamAsync();
                ResponseType responseObject = DeserializeResponse<ResponseType>(responseStream);
                if (responseObject != null)
                {
                    responseObject.Success = true;
                    return responseObject;  //The code successfully reach this line. After this nothing happens
                }
                else
                {
                    log.Error("Response could not be deserialized");
                }
            }
            else
            {
                log.Error("Error during request, got status code " +  response.StatusCode);
            }
        }
    }
    catch (Exception e)
    {
        log.Error("Something went wrong!", e);
    }
    return new ResponseType() { Success = false };
}
5
  • 2
    You haven't shown the method that calls SendOrder - that's most likely where your issue is. Async needs to be async all the way up - if there's any method in the chain that returns something that isn't a task, the chain is broken. Commented Aug 31, 2015 at 7:41
  • Yes, it could be a deadlock, considering that the return-statement in the ExecuteRequest is reached, but not the next statement after await SendOrder. Deadlocks of this kind are often caused by using Task.Result or Task.Wait or any similar construct that blocks the current thread. Commented Aug 31, 2015 at 7:46
  • added more code to the first code block to show the entire method Commented Aug 31, 2015 at 7:58
  • added the entire method chain for when the calls start. The top method is the first method called Commented Aug 31, 2015 at 8:13
  • ExecuteTaskAsync(token, order).Wait();, this is basically a Task.Wait(), which will block the current thread so there's no way the rest (after the await) is executed, effectively deadlocking Commented Aug 31, 2015 at 8:16

1 Answer 1

4

The problem is on this line:

ExecuteTaskAsync(token, order).Wait();

This causes a deadlock: the awaits in the called method can't resume because the UI thread is blocked.

When you use async code, you must use it all the way; never wait synchronously for an async task to complete.

Sign up to request clarification or add additional context in comments.

10 Comments

I'd say the "current thread", not necessarily the "UI" one in this case, but yes, that's what I said in my comment too :-)
@Jcl, typically, only the UI thread has a synchronization context, so the problem only occurs on that thread.
That's right, I typically confuse "UI" with "GUI" so I was not keen on calling it the "UI thread" on a webservice... but yes, you are right indeed, my bad
If I remove the Wait() I get an InvalidOperationException which says: "An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle."
@Mattias, ah, didn't know it was an ASP.NET app. The problem remains, though; you don't have a UI thread, but you do have a synchronization context. Anyway, I wasn't suggesting that you don't wait for the task at all; I was suggesting that you await it, which means that you must change ExecuteTask to be async as well.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.