VMesser
@VMesser
gitter.im/VBA-developers

Почему методы без await исполняются последовательно?

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

Может это какая-то магия передачи управления? Например, компилятор знает, что если мы в конечном счёте исполняем http запрос, то надо бежать прочь отсюда к следующему методу основного потока управления, а если там какие-то вычисления, то надо дождаться их исполнения, и не покидать метод.
Или это ещё как-то работает?
  • Вопрос задан
  • 161 просмотр
Решения вопроса 1
vabka
@vabka Куратор тега C#
Токсичный шарпист
почему считается, что методы без await выполняются гарантированно последовательно?

Потому что так компилятор работает.
Передача управления может произойти только там, где стоит await.
=> Если в async Task методе нет ни одного await, то метод будет выполняться синхронно от начала до конца, без передачи управления другим потокам
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
twobomb
@twobomb
Ну если при отправке 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");
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы