Возможно ли, что асинхронный код занимает больше времени, чем синхронизация? - PullRequest
0 голосов
/ 17 мая 2018

У меня есть фрагмент кода, который выполняет HTTP-запросы (внутри цикла) от некоторого валютного API и выполняет некоторую работу с полученными данными.

Поскольку это было медленно, я изменил его на асинхронную функцию, используя: Task.Run ()

Однако, когда я измеряю время расчета (используя секундомер ..) функции с помощью асинхронного метода это занимает больше времени (или даже), чем синхронный.

Как это возможно? Я делаю это неправильно?

[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();
    }
}

Пример кода функции синхронизации:

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;
        }
}

Пример асинхронности:

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;
        }
    }

Код функции 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);
                }

             }
      }
}

1 Ответ

0 голосов
/ 17 мая 2018

попробуйте прочитать этого парня:

он в нескольких словах рассказывает, как это работает,Суть в том, что при использовании async / await вы получаете некоторые накладные расходы, однако вы освобождаете ресурсы.Поэтому любая задача, которая будет выполняться, будет выполняться в синхронизированном контексте.но вы можете обрабатывать гораздо больше запросов.

Помимо того факта, что вы на самом деле не используете асинхронную функциональность с .result, вы фактически убивает асинхронную часть.

В короткой строке асинхронное выполнение не обязательно ускоряет его.Если у вас есть больше задач, связанных с ЦП, которые могут выполняться одновременно, вы увеличите производительность, однако в вашем случае вы не увеличите производительность, а ресурсы, подобные Кевину в своих комментариях.

надеюсь, что это поможет!

...