Подтвердить что ты не робот

Вызывать метод асинхронного вызова без ожидания # 2

У меня есть метод async:

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;
}

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

ИЗМЕНИТЬ

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

4b9b3361

Ответ 1

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

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

ValidateRequestAsync(userName, password).Result

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

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

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

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

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