вызов асинхронного метода без ожидания #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



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

602   2  

2 ответов:

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

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

ValidateRequestAsync(userName, password).Result

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

Есть способы предотвратить этот тупик, но все они-плохая идея. Просто для полноты картины может сработать следующее:
Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

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

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

Можно использовать return ValidateRequestAsync (имя пользователя, пароль).Помощью getawaiter().GetResult ();

Comments

    Ничего не найдено.