Тупик при вызове асинхронного метода внутри неасинхронного действия - PullRequest
0 голосов
/ 01 октября 2019

У нас есть веб-приложение, которое состоит из веб-API, используемого нашим пользовательским интерфейсом. Веб-приложение установлено на разных серверах (тестируется перед его установкой нашими клиентами).

На одном сервере мы заходим в тупик со следующей конечной точкой:

[HttpGet, Route(Order = 1)]
public IHttpActionResult GetUserDetails(long userKey)
{
    var userService = ResolveService<IUserService>();
    var nameService =  ResolveService<INameService >();

    LoggInfo("Start userService.Get()"); //logged in logs
    var result = userService.Get(userKey);
    this.LoggInfo($"End userService.Get() with id = "{result.Id}); // logged in logs

    try
    {
      LoggInfo($"Start nameService.Get()"); // logged in logs
      result.Name =  nameService.Get(result.Namekey).Result?.Name;
      LoggInfo($"End nameService.Get()"); // not logged in logs
    }
   catch(Exception ex)
   {
     LogError("An error occured in NameService"); // not logged in logs
   }

    return Ok(result);
}

nameService.Get(id) isasync метод:

public async Task<NameDTO> GetAsync(long key)
{
    LogInfo("start NameService.Get()"); // not logged in logs
    var query = GetQuery();
    var name = await query.Select(MapName())
                          .FirstOrDefaultAsync(n => n.Key == key);

    return name;
}

Когда я удаляю асинхронную подпись, все работает как положено, согласно этой статье это нормально, чтобы иметь тупик.

Не могли бы вы объяснить, почему это работает на других серверах?

Заранее спасибо за вашу помощь

1 Ответ

2 голосов
/ 01 октября 2019

Не могли бы вы объяснить, почему это работает на других серверах?

Для того, чтобы возникла тупиковая ситуация , есть три необходимые части:

  1. Однопотоковый контекст, который будет иметься у всех серверов (до ядра ASP.NET).
  2. await (без ConfigureAwait(false)) действует асинхронно .
  3. Код в другом месте, который блокирует поток внутри этого контекста, ожидая завершения метода async. Все серверы также имеют это.

Скорее всего, разница в поведении обусловлена ​​второй частью: await, которая действует асинхронно. await сначала проверяет его ожидаемое (например, переданное ему Task), и если это ожидаемое завершено, то он продолжает выполнять async метод синхронно .

В частности, это произойдет, если Task<NameDTO> вернется из GetAsync завершено до , когда вызывающий код достиг .Result. Это должно быть очень быстро, но это возможно в зависимости от кэширования, скорости вашего сетевого прыжка, замедления кода из-за загрузки / соседей / антивируса и т. Д.

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