Функция еще асинхронная может быть улучшена?

1

У меня есть эта функция:

public async Task<string> EagerLoadAllAsync<T>(params Expression<Func<T, object>>[] includeProperties) where T : class
{
    var entities = await _repository.EagerLoadAllAsync(includeProperties);
    entities.ForEach(l =>
    {
        var lead = l as Lead;
        if (lead.User != null) 
        {
            // We must reduce the amount of data being sent to the client side
            lead.User = new Domain.Identities.ApplicationUser { FirstName = lead.User.FirstName, LastName = lead.User.LastName, UserName = lead.User.UserName };
        }
    });

    var json = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(entities, Formatting.Indented, new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    }));

    return json;
}

Я думаю, что все еще async работает с awaitable функциями, один - для извлечения данных из базы данных, а другой - для преобразования json.

Мне было интересно, если цикл ForEach в среднем типе разрушает async подход?

Есть ли способ сделать это более async? Должно ли быть более async?

Прежде чем мне нужно было уменьшить данные, отправляемые клиенту, у меня была эта функция:

public async Task<string> EagerLoadAllAsync<T>(params Expression<Func<T, object>>[] includeProperties) where T : class
{   
    var json = await Task.Factory.StartNew(async() => JsonConvert.SerializeObject(await await _repository.EagerLoadAllAsync(includeProperties), Formatting.Indented, new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    }));

    return json.Result;
}
Теги:
asp.net-mvc
async-await
asynchronous

2 ответа

3
Лучший ответ

У Stephan cleary есть отличная запись в блоге об the dangers of using Task.Run in ASP.NET:

Причина в том, что среда выполнения ASP.NET не имеет представления о том, что вы поставили эту задачу в очередь (используя Task.Run), поэтому она не знает, что фоновая работа даже существует. По разным причинам IIS/ASP.NET приходится периодически перерабатывать ваше приложение. Если у вас есть фоновая работа, когда эта переработка происходит, эта работа загадочно исчезнет.

Когда я создаю метод async вокруг некоторой асинхронной операции (запрос БД, веб-запрос и т.д.), Я придерживаюсь правила, в котором говорится, что "метод async должен как можно скорее ударить его утверждение await ", то есть, поскольку любой код до ожидание будет выполняться синхронно. Вы можете использовать ConfigureAwait(false) чтобы избежать возврата в контекст вашего запроса, но это обычно происходит очень быстро. См. " Лучшая практика" для вызова ConfigureAwait для всего кода на стороне сервера, чтобы узнать больше об этом.

Что ForEach, я бы определенно оценил эту часть, чтобы увидеть, насколько значительным было влияние на асинхронный вызов. Другое тогда, что прочитайте eric lipperts сообщение о ForEach vs foreach чтобы понять, почему вы не должны его использовать.

Я бы определенно перешел на новый поток ThreadPool только ради десериализации JSON. Это будет стоить вам больше, чтобы вызвать этот поток, чтобы запустить его синхронно. Если ваш JSON не огромен, пойдите с подходом синхронизации.

  • 0
    Я прочитал это на самом деле на днях, не знал, почему я не подхватил его, слишком устал устал: P
  • 1
    Мой пост в блоге на самом деле говорит об использовании Task.Run / Task.Factory.StartNew / etc без await . Если вы используете await , то код Task.Run логически считается частью этого запроса и не «исчезнет». Однако я все еще не рекомендую Task.Run на ASP.NET по соображениям эффективности.
Показать ещё 1 комментарий
1

Обычно вы ожидаете задачи, которые относительно длительные, как I/O. Итак, ожидание вашего звонка на выборку репозитория - это хорошо. Ваш цикл ForEach совсем не плох, но он, вероятно, будет работать лучше, если ваш выбор из репозитория вернет только нужные вам данные, поскольку он не вернет все эти данные.

Я не уверен, что если вы перейдете к другой задаче, чтобы преобразовать сущности в json, вы делаете все возможное.

И тогда мы должны учитывать, что это веб-вызовы и ждут, просто освобождая обработчик запросов, чтобы он не мог ускорить каждый индивидуальный вызов, он просто не свяжет запрос, который сидит там, ожидая ввода/вывода базы данных,

Вы всегда можете поставить некоторые Stopwatches чтобы посмотреть, как долго все это происходит.

  • 0
    Да, именно об этом я и думал, в модели запрос-ответ это не имеет большого значения. Я следил за преобразованием, которое JSON.NET показывает в его примерах, если в хранилище много информации, тогда выполнение фоновой задачи может быть просто нормальным.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню