вызов async-метода без await #2

У меня есть асинхронный метод:

public async Task<bool> ValidateRequestAsync(string userName, string password)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        string stringResponse = await response.Content.ReadAsStringAsync();

        return bool.Parse(stringResponse);
    }
}

Я вызываю этот метод следующим образом:

bool isValid = await ValidateRequestAsync("user1", "pass1");

Могу ли я вызвать тот же метод из синхронного метода, не используя ключевое слово await?

Например:

public bool ValidateRequest(string userName, string password)
{
    return ValidateRequestAsync(userName, password).Result;
}

Я думаю, что это приведет к тупику.

EDIT

Вызов метода, как описано выше, приводит к тому, что вызов никогда не заканчивается. (Метод больше не достигает конца)

Комментарии к вопросу (8)
Решение

Если вызывать async-метод из однопоточного контекста выполнения, например из потока UI, и ждать результата синхронно, то велика вероятность возникновения тупиковой ситуации. В вашем примере эта вероятность составляет 100%.

Подумайте об этом. Что происходит, когда вы вызываете

ValidateRequestAsync(userName, password).Result

Вы вызываете метод ValidateRequestAsync. В нем вы вызываете ReadAsStringAsync. В результате задача будет возвращена в поток UI, а ее продолжение запланировано для продолжения выполнения в потоке UI, когда он станет доступен. Но, конечно, он никогда не станет доступным, поскольку ожидает (блокируется) завершения задачи. Но задача не может завершиться, так как ждет, пока поток UI станет доступным. Тупик.

Существуют способы предотвратить этот тупик, но все они являются плохой идеей. Для полноты картины можно привести следующий вариант:

Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

Это плохая идея, поскольку вы все равно блокируете поток UI, ожидая и не делая ничего полезного.

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

Комментарии (7)

можно использовать return ValidateRequestAsync(userName, password).GetAwaiter().GetResult();

Комментарии (2)