Vicky
Vicky

Reputation: 23

httpclient async/await or not

I'm using one httpclient instance to send multiple requests to rest web api to get data. Here is what my code looks like:

First I have a control layer that calls the data layer for data.

public class ControlLayer
{
    protected DataLayer dal;

    //constructors here

    public int getInfo1(int param)
    {
      int ret = this.dal.getInfo1(param);
      return ret;
    }

    public int getInfo2(int param)
    {
      int ret = this.dal.getInfo2(param);
      return ret;
    }
}

then I have the dataLayer that calls webAPI, it looks like this. here for simplicity, im using .result directly.

public class DataLayer
{
    HttpClient client = new HttpClient();
    string url = "";

    public int getInfo1(int param1)
    {
      int ret=0;
      HttpResponseMessage response = client.GetAsync(url).Result;
      //.... do some work, get the value for ret

      return ret;
    }

    public int getInfo2(int param1)
    {
      int ret = 0;
      HttpResponseMessage response = client.GetAsync(url).Result;
      //.... do some work, get the value for ret

      return ret;
    }
}

my questions is I've seen some tutorials saying that we should avoid using .result, because it might lead to deadlock. I'm not sure in my case do I need to use async/await? if I do need, I know I should async all the way down, but I do want my controlLayer to be sync, because I have other layer that calls the controlLayer's function, I don't want all the layer's function to be async and the result be Task<>, is this a situation of sync over async? am I miss something? any suggestions are appreciated. thanks!

Upvotes: 2

Views: 12791

Answers (2)

sinelaw
sinelaw

Reputation: 16563

You only need to use async and await if your code is asynchronous - for example if it dispatches several requests simultaneously, doing work after a request is sent instead of just blocking until the response arrives.

Ignoring the deadlock issue for a moment - if your code is simply synchronous, that is: every time you send a request you just wait for the response before doing anything else, you don't need to use await and can use Result. See this question for a similar debate. Alternatively, you can use a synchronous API (such as WebClient as suggested in the comments and other answer).

As for Result-related deadlocks, I recommend you read this article on MSDN for a better understanding of what happens and why. If you're writing a simple console application, you don't really need to worry about it (the right way to deal with it is to have only your Main method non-async, and use Result or Wait there).

Upvotes: 5

Stephen Cleary
Stephen Cleary

Reputation: 457217

I do want my controlLayer to be sync, because I have other layer that calls the controlLayer's function, I don't want all the layer's function to be async and the result be Task<>

I recommend you rethink this. A web request is a fundamentally asynchronous operation, so I recommend that you expose your "control layer" as an asynchronous API and allow the async to "grow" through the layers in your code base.

However, if you really want a synchronous API, then you should only call synchronous APIs. E.g., use WebClient instead of HttpClient. Do not call Result to wrap an asynchronous API with a synchronous API.

Upvotes: 7

Related Questions