Страницы

Поиск по вопросам

вторник, 23 октября 2018 г.

Где правильно использовать async/await в WebAPI

Мы никогда не использовали async/await (или что-то подобное) в нашем небольшом проекте. Но сейчас проект растет, и мы решили добавить асинхронность.
Проект имеет следующую архитектуру:
Domain (репозиторий, EF) UnitTests Service (новый, тут планируется перенести бизнес логику с контроллеров) WebUI
Мой вопрос, в каком слое мы должны реализовать асинхронность? Или мы должны сделать это на нескольких слоях? Пожалуйста, подскажите мне, где реализация будет наиболее подходящей?
Например у меня есть метод в контроллере
public virtual HttpResponseMessage Get() { var entity = Repository.GetAll();
if (entity != null && entity.Any()) { return Request.CreateResponse(HttpStatusCode.OK, entity); }
var message = $"{GenericTypeName}: No content"; return ErrorMsg(HttpStatusCode.NoContent, message); }
Как мне сделать его асинхронным?


Ответ

class Repository { public Task GetAllAsync(CancellationToken cancellationToken) { return Task.Run(() => { // тут что-то ресурсоёмкое вычисляем
return entity; // возвращаем результат }); } }
Второй пример, то же самое только с async await
class Repository { public async Task GetAllAsync(CancellationToken cancellationToken) { // вернёт управление в вызывающий код await Task.Yield(); // тут что-то ресурсоёмкое вычисляем
return entity; // возвращаем результат } }
Третий пример, если нужно перед возвратом данных вычислить, что-то параллельно
class Repository { public async Task GetAllAsync(CancellationToken cancellationToken) { var tasks = new List(); tasks.Add(Task.Run(() => { // тут что-то ресурсоёмкое вычисляем
return entity; // возвращаем результат })); tasks.Add(Task.Run(() => { // тут что-то ресурсоёмкое вычисляем
return entity; // возвращаем результат })); tasks.Add(Task.Run(() => { // тут что-то ресурсоёмкое вычисляем
return entity; // возвращаем результат })); // дожидаемся окончания всех задач await Task.WhenAll(tasks);
// дальше пробегаемся по списку задач, получаем результат работы каждой и что-то с ним делаем. И возвращаем уже вычисленный нами результат. } }
Конечно в реальном боевом приложении код будет немного другой и зависеть от конкретной задачи но принцип будет один и тот же.
Обращаю внимание, что async/await это синтаксическая обёртка над Task.Run с некоторыми отличиями. А отличия в обработке исключений в процессе выполнения задачи.
Но прежде чем писать асинхронный код обязательно прочитайте про async/await И task иначе будет множество ошибок. Особенно внимательно нужно смотреть обработку исключений.

Комментариев нет:

Отправить комментарий