Пытаюсь разобраться с async/await.
Вызываю асинхронный метод:
public static async Task<Data> GetData(string url)
{
dynamic results = await DataService.getData(url);
}
Cам метод:
public static async Task<dynamic> getData(string url)
{
HttpClient client = new HttpClient();
var response = await client.GetAsync(url);
while(true){} // специально сделанное зацикливание, чтобы увидеть что UI не блокируется
dynamic data = null;
if(response !=null)
{
string json = response.Content.ReadAsStringAsync().Result;
data = JsonConvert.DeserializeObject(json);
}
return data;
}
Однако при вызове этого метода всё зависает. Почему все зависает, ведь на сколько я понимаю, async\await должен создаваться в отдельном потоке и следовательно не должен блочить UI, а просто зацикливаться в "фоновом" потоке?
Нет, вы понимаете неправильно.
Если async-функция запущена в UI-потоке, она в нём и выполняется (это можно легко увидеть, залогировав Id потока), за исключением await’ов, во время которых функция вообще нигде не выполняется (и тем самым освобождает UI-поток). Иначе как бы можно было получать доступ к UI-контролам в async-функции? Уберите вечный цикл, он завешивает UI.
Что потенциально может вывести async-функцию в другой поток — это ConfigureAwait(false)
, но в вашей функции его нет.
У вас ошибка в строке
string json = response.Content.ReadAsStringAsync().Result;
Вы не должны синхронно дожидаться завершения Task’а ReadAsStringAsync()
. Замените это на
string json = await response.Content.ReadAsStringAsync();
Кстати, у вас есть ещё одна потенциально медленная операция в UI-потоке: JsonConvert.DeserializeObject(json)
. Вынесите её в фоновый поток при помощи
data = await Task.Run(() => JsonConvert.DeserializeObject(json));
По поводу механики (как именно работает async-функция на нижнем уровне) можно почитать, например, тут, тут, тут, тут, тут и тут. И посмотреть тут.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Если использовать обычный webBrowser, то можно вытащить HTML таким образом
Нужно плавно повысить у компонента background радиус блюра с 0 до 20, с помощью кода, то есть анимировать свойство radius в эффекте BlurEffect
Столкнулся с проблемой в элементе управления SystemWindows