Позвольте мне указать несколько вещей, с функциями:
public async Task<Client> GetClient()
{
return await _clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefaultAsync();
}
Это первая функция немного расточительно. Ни async
, ни await
не дают вам никакой пользы. Почему я так говорю? Хорошо, давайте просто быстро рассмотрим обычное преимущество await
.
Что может сделать await
- это возобновление выполнения остатка метода после завершения ожидаемой задачи. В вашем случае нет «остатка метода», поскольку return await
является последней инструкцией метода.
Почему это расточительно? Ну, помечая свой метод async
, вы в основном говорите компилятору, чтобы сгенерировать все оборудование (то есть конечный автомат), чтобы вы могли возобновить выполнение внутри этого же метода после каждого ожидания.
Эта техника бесполезна в вашем случае, так как нет ничего после AWAIT возобновить выполнение, так что вы лучше не маркировки метода async
и вместо return await
просто сделать простой возврат задачи, порожденной FirstOrDefaultAsync
.
Выполнение этого будет по-прежнему возвращать функцию и вести себя асинхронно. Имейте в виду, что async
и await
на самом деле не выполняют функцию асинхронно.async/await
просто помогают настроить механизм для обеспечения «закладок» в различные точки ожидания вашего метода, чтобы выполнение могло возобновиться там после завершения каждой ожидаемой задачи.
Теперь давайте поговорим о вашей второй функции:
public Task<Client> GetClient2()
{
return Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault());
}
Эта функция не асинхронной вообще. Он выполнит полностью синхронный и не даст нить вообще.
Даже если вы сделали это:
public async Task<Client> GetClient2()
{
return await Task.FromResult(_clientRepository.GetAll().Where(x => x.Id == 1).FirstOrDefault());
}
Функция по-прежнему будет полностью синхронным. Помните, что async/await
- все о настройке машин и закладок, но на самом деле не играют никакой роли в том, будет ли код выполняться синхронно или асинхронно.
Так почему же это блокирование? Поскольку FirstOrDefault()
не возвращает задачу, значит, она должна вернуть объект Client
. Это означает, что он не может вернуть ничего, пока он полностью не завершит выполнение цепочки linq
. Затем ваш Task.FromResult
просто принимает это значение и завершает его в предварительно выполненной задаче.
Так просто резюмировать:
использовать только async/await
если вам нужно возобновить выполнение где-то в середине вашего метода.
Пример:
public async Task<boolean> IsIntegerIGetFromRemoteServerPostitiveAsync(){
int result = await GetSomeIntegerAsync();
Console.WriteLine('Resuming execution of the method');
return i>0;
}
Если вы обнаружите, что у вас есть один ОЖИДАНИЕ и это последняя строка метода не используйте async/await
, просто вернуть задание вместо ожидании его. Это позволяет избежать лишних накладных расходов.
Пример:
public Task<string> GetUserInformationAsync(string username){
var url = $"http://userinfo.com?username={username}"
return GetSomeJsonFromHttpServerAsync(url); //Assuming this returns Task<string>
}
Я рекомендую прочитать эту статью [] (http://davidwalsh.name/async-generators), это объясняет асинхронный/Await от точки генератора/обещания зрения. – MinusFour
Они совершенно разные и даже вызывают разные методы внутри ... Как вы ожидаете, что эти два метода будут одинаковыми? –
Делает _clientRepository.GetAll(). Где (x => x.Id == 1) .FirstOrDefaultAsync(); равно Task.FromResult (_clientRepository.GetAll(). Где (x => x.Id == 1) .FirstOrDefault()); – user1075940