Comments 24
Спасибо. Понятно и разложено по полочкам.
Вообще я очень благодарен команде C# за async/await, а то последнее время код стал превращаться в что-то jQuery-подобное, когда линейный код выглядел как 20 вложенных анонимных функций.
Вообще я очень благодарен команде C# за async/await, а то последнее время код стал превращаться в что-то jQuery-подобное, когда линейный код выглядел как 20 вложенных анонимных функций.
+7
AsyncEnumerator — «наше всё» уже 2+ года, тем более, что для его использования достаточно C# 2.0 и .Net Framework 2.0.
А так, конечно, хочется уже и без «костылей» асинхронный код в линейном виде писать.
А так, конечно, хочется уже и без «костылей» асинхронный код в линейном виде писать.
0
Производительность: предпочитайте кэшировать сами задачи, нежели их данныеНесколько капитанский совет получился. Я с трудом представляю себе метод, который кэширует данные, но при этом возвращает задачи. Он что, возвращает только уже выполненные задачи? Хотелось бы увидеть работающий пример плохого и неправильного кода.
Производительность: понимайте, как await сохраняет состояниеНе может. Поля объекта, относящиеся к выходящим из области видимости переменным, обNULLяются автоматически.
Замечание 1. Если вы декларируете переменную, она сохранится в объекте, хранящем состояние. Это может привести к тому, что объекты будут оставаться в памяти дольше, чем вы бы могли ожидать.
Замечание 2. Но если вы не станете декларировать переменную, а использовать значение Async вызова вместе с await, переменная попадёт во внутренний стек:
Результат вызова await всегда попадает в поле — по другому компилятор просто не умеет.
+2
Вы заблуждаетесь, это верно только если метод не использует async/await.
А если использует, то вычисленные значения попадают не в локальную переменную метода (или что вы имели в виду под «полем»), а в стек стейт-машины в его поле:
Здесь описано как это работает, а в ILSpy вы можете посмотреть какой код генерирует компилятор (если отключите декомпиляцию async/await).
А если использует, то вычисленные значения попадают не в локальную переменную метода (или что вы имели в виду под «полем»), а в стек стейт-машины в его поле:
private object <>t__stack;
Здесь описано как это работает, а в ILSpy вы можете посмотреть какой код генерирует компилятор (если отключите декомпиляцию async/await).
0
А если использует, то вычисленные значения попадают не в локальную переменную метода (или что вы имели в виду под «полем»), а в стек стейт-машины в его поле
Вы издеваетесь или как? Именно это поле я и имел в виду. При чем тут локальная переменная метода?
PS Проверил в ILSpy, нет там обNULLения, я ошибся. Странно, где же я его видел?
0
Ну я то думал, что внутренний стек == поле <>t__stack; и тогда не понятно, что же вы имели в виду?
Однако, автор же, очевидно, просто имел в виду то, что если вы используете await в параметре, то значение будет храниться в этом поле, а если присваиваете результат await переменной — для неё компилятор сделает собственное поле в стейт-машине (что будет быстрее работать, нежели расширять Tuple-ы со значениями для параметров и класть их в t__stack в рантайме).
Однако, автор же, очевидно, просто имел в виду то, что если вы используете await в параметре, то значение будет храниться в этом поле, а если присваиваете результат await переменной — для неё компилятор сделает собственное поле в стейт-машине (что будет быстрее работать, нежели расширять Tuple-ы со значениями для параметров и класть их в t__stack в рантайме).
0
Значит у вас плохая фантазия. Кешировать данные — более очевидно чем таски. Ибо долго достаются именно данные, а не создаются таски.
0
Очевидно-то более, но я не представляю, как будет работать параллельное получение данных с кэшированием этих самых данных. Вот и хочется посмотреть на получившийся код того человека, который не догадался до кэширования тасков.
0
мне понравился один комментарий к stackoverflow.com/questions/6023264/high-performance-tcp-server-in-c-sharp:
Long story short: learn async or die trying…
Long story short: learn async or die trying…
+3
«Лучшие практики» — это вообще что значит? Какой это язык?
0
Предпочитайте async/await вместо Task
Но внутри MyWebService.FetchDataAsync() будет return Task.Factory.StartNew(() =>…
Как-то не получается вместо. Получается вместе. Может кто-нибудь прояснит этот момент?
0
Вы одновременно и правы и не совсем правы :)
Вообще говоря async/await работает поверх awaitable типов, самый очевидный из которых Task, и в самом простом случае конечно async/await это _надстройка_ над Task.
Но awaitить можно не только Task, а любой тип реализующий await контракт (наличие метода GetAwaiter возвращающего объект с property IsCompleted, методом OnCompleted(Action) и методом T GetResult())
Это довольно важно в случае с overlapped IO, когда для ожидания результата IO не нужна отдельная нить( а Task работает именно с нитями через ThreadPool)
Вообще говоря async/await работает поверх awaitable типов, самый очевидный из которых Task, и в самом простом случае конечно async/await это _надстройка_ над Task.
Но awaitить можно не только Task, а любой тип реализующий await контракт (наличие метода GetAwaiter возвращающего объект с property IsCompleted, методом OnCompleted(Action) и методом T GetResult())
Это довольно важно в случае с overlapped IO, когда для ожидания результата IO не нужна отдельная нить( а Task работает именно с нитями через ThreadPool)
0
ConfigureAwait(false) надо использовать в любом коде, который не нуждается в доступе к потоку UI, но запускается из потока UI, иначе управление будет постоянно возвращаться к нему и часть работы будет выполняться в потоке UI. Запустите профайлер Visual Studio и убедитесь в этом.
Короче, я не использую ConfigureAwait(false) только в асинхронных обработчиках событий от UI.
Короче, я не использую ConfigureAwait(false) только в асинхронных обработчиках событий от UI.
+2
Интересная статья, но машинный перевод удручает.
Не переводите то что переводить не нужно. Reentrance, SynchronizationContext (это банально класс), SecurityContext (тоже)
Машина состояний это в данном случае конечный автомат, контекст ASP.NET — это Request Context.
"… по выбору функциональсти, которая должна быть асинхронной." — choosing methods that should be async. Тут странная замена методов на функциональность.
"… я предпочитаю async/await вместо создания цепочек задач посредством Task." — I prefer async/await to setting up Task chains
Вы как то легко вставляете слово «задач». Ведь тут речь не о цепочках задач, а о цепочках Task. Первое — это нечто абстрактное, а второе — технический прием.
Не переводите то что переводить не нужно. Reentrance, SynchronizationContext (это банально класс), SecurityContext (тоже)
Машина состояний это в данном случае конечный автомат, контекст ASP.NET — это Request Context.
"… по выбору функциональсти, которая должна быть асинхронной." — choosing methods that should be async. Тут странная замена методов на функциональность.
"… я предпочитаю async/await вместо создания цепочек задач посредством Task." — I prefer async/await to setting up Task chains
Вы как то легко вставляете слово «задач». Ведь тут речь не о цепочках задач, а о цепочках Task. Первое — это нечто абстрактное, а второе — технический прием.
0
Используйте async /await только для тех мест, которые могут длиться «долго»
Не совсем корректно. async/await подходит для IO-bound операций, т.е. работа с сетью, диском, где код ничего не делает, а сидит и ждет ответа на IO порт. Для CPU-bound задач, которые тоже могут длиться «долго» и потребляют ресурсы постоянно, разумнее использовать параллелизацию и фоновые потоки.
0
Sign up to leave a comment.
Использование async и await в C# — лучшие практики