O. H
O. H

Reputation: 97

Is it possible that async code takes more time than sync?

I have a piece of code that execute HTTP requests (inside a loop) from some currency API and do some work on the data which received.

Because it was slow, I changed it to asynchronously function using: Task.Run()

However, when I measure calculation time (using Stopwatch..) of the function with the async method, it takes more time (or even) than the sync one.

How can it possible? Am I do it wrong?

[HttpPost,Route("GetCurrenciesData")]
public IHttpActionResult GetCurrenciesData(InputCurrenciesData cls)  
{
    try
    {
        var watch = Stopwatch.StartNew();

        var data2 = GetBL.mySyncMethod(cls.currenciesList);

        watch.Stop();
        string first = watch.Elapsed.ToString();  // --> this faster
        watch = Stopwatch.StartNew();
        var data = GetBL.myAsyncMethod(cls.currenciesList);
        string second = watch.Elapsed.ToString();  // --> this slower
        return Ok(data);
    }
    catch (Exception ex)
    {
        getGeneric.WriteError(ex.Message, ex.StackTrace);
        return BadRequest();
    }
}

Example code of the sync function:

public GenericClass mySyncMethod(string[] currencies)
{
        try
        { 
            foreach (string currency in currencies)
            {

                getDataFromApi(currency);
            }


            return getDataChart;

        }
        catch (Exception ex)
        {
            WriteError(ex.Message, ex.StackTrace);
            return null;
        }
}

Example of the async :

public GenericClass myAsyncMethod(string[] currencies)
    {
        try
        {
            List<Task> TaskList = new List<Task>();

            foreach (string currency in currenies)
            {

                var myTask = new Task(() =>
                {
                    getDataFromApi(currency);
                });
                myTask.Start();
                TaskList.Add(myTask);

            }

            Task.WaitAll(TaskList.ToArray());

            return getDataChart;

        }
        catch (Exception ex)
        {
            WriteError(ex.Message, ex.StackTrace);
            return null;
        }
    }

The code of the function getDataFromApi:

private void getDataFromApi(string currency)
    {

        string currencyCode = getCurrenciesDictionary[currency];

//Get api's URL from Web.config and concatenation the wanted currency code
        string URL = string.Format(GetConfig("Api"), currencyCode);  

        /*HTTP request to retrieve data from Api*/
        using (HttpClientHandler handler = new HttpClientHandler())
        {
            handler.UseDefaultCredentials = true;
            using (HttpClient httpClient = new HttpClient(handler))
            {
                var ResultAsync = httpClient.GetAsync(URL).Result;
                if (ResultAsync.IsSuccessStatusCode)
                {
                    var content = ResultAsync.Content;

                    string Data = content.ReadAsStringAsync().Result;

                    try
                    {
                        var ret = JsonConvert.DeserializeObject<RootObject>(Data);


                        /*add new class to currencyRate list - class which represent the currency and its rates*/
                        getDataChart.CurrencyRate.Add(new CurrencyRate
                        {
                            Currency = currency,
                            Rates = ret.dataset.data.AsEnumerable().
                                    Select(date => Double.Parse(date[1].ToString())).ToList()
                        });


                    }
                 catch (Exception ex)
                 {
                    WriteError(ex.Message + " currency: " + currency + "/n/ URL: " + URL, ex.StackTrace);
                }

             }
      }
}

Upvotes: 1

Views: 1951

Answers (1)

Roelant M
Roelant M

Reputation: 1706

try and read some of this guy:

he's telling in a few words how it works. The main point is that you get some overhead using async/await, however, you're freeing resources. So any task that will run, will run on the synchronized context. but you can handle much more request.

Besides the fact that you are not really using async functionality with the .result kills actually the async part.

In a short line, doing it async doesn't necessarily speed it up. If you have more CPU-bound tasks, that can run simultaneously you will major performance, however, in your case, you will not performance, but resources like Kevin tells in his comments.

hope it helps!

Upvotes: 3

Related Questions