Ну если при отправке http запроса вы используете какой-то его асинхронный метод, то да поток не блокируется, потому-что тот метод выполняется на другом потоке, а если вы в своей асинхронной функции будете использовать синхронные методы работы с http запросом, то и поток ваш будет блокироваться при их использовании.
Вообще как мне кажется эти async,await добавлены больше для удобства и простого отлавливания исключений возникающих в методах выполняющихся на других потоках.
Если раньше мне нужно было писать что-то типа такого:
private void Button_Click(object sender, RoutedEventArgs e){
var t = new Task(() =>{
//дейтсвия выполняющиеся в другом потоке
Thread.Sleep(1000);
});
t.ContinueWith(new Action<Task>((task) =>{//вызываем по завершению работы таски
Dispatcher.Invoke(new Action(() =>{//вызываем в основном потоке, потому-что обращения к gui элементам может быть только через него
try{
if (t.IsFaulted)//если у нас возникло исключение в нашей первой таске вызываем его здесь что уловить его тут и обработать
throw t.Exception;
textblock.Text = "my text";
}
catch (Exception exception){
Console.WriteLine(exception);
}
}));
}));
t.Start();
}
То сейчас достаточно так:
private async void Button_Click(object sender, RoutedEventArgs e){
try{
await Task.Run(() =>{
//дейтсвия выполняющиеся в другом потоке
Thread.Sleep(1000);
});
textblock.Text = "my text";//и мы волшебно продолжаем выполнение в главном потоке
}
catch (Exception exception){//будет вызван даже если возникнет исключение в таске
Console.WriteLine(exception);
}
}
Ну если вам нужно выполнить сразу несколько методов асинхронно и ждать их выполнение через await можно сделать так
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() =>{
Thread.Sleep(1000);
Console.WriteLine("1");
}));
tasks.Add(Task.Run(() =>{
Thread.Sleep(1000);
Console.WriteLine("2");
}));
tasks.Add(Task.Run(() =>{
Thread.Sleep(1000);
Console.WriteLine("3");
}));
await Task.WhenAll(tasks.ToArray());
Console.WriteLine("continue");