Как работает асинхронность в C#

Поделиться
HTML-код
  • Опубликовано: 14 ноя 2024

Комментарии • 30

  • @Easycore2000
    @Easycore2000 8 месяцев назад +23

    Было бы круто посмотреть полный ролик про пул потоков и планировщик задач)

  • @WWo3CG
    @WWo3CG 7 месяцев назад +7

    Немного скорректировать бы))
    Понятия главного потока нету и после асинхронного вывода не всегда именно вызывающий поток продолжит выполнения, хотя у него и есть приоритет.
    Так же само понятие асинхронности применимо не везде, где стоит async. Основное что следует учить в асинхронности - это то, что асинхронное выполнение происходит на других мощностях(удаленный сервер, I/o операции и т.д.), если такого нет, то все будет запущено в синхронном режиме и ни чего кроме лишней памяти и возможной просадки производительности не будет))

    • @TheMybabloo
      @TheMybabloo 6 месяцев назад

      А если тебе тяжелые вычисления нужно распараллелить?

    • @AndrewT-e6f
      @AndrewT-e6f 6 месяцев назад +2

      ​@@TheMybablooТогда это уже будет многопоточность

    • @lex-xv3ik
      @lex-xv3ik 2 месяца назад +1

      @@AndrewT-e6f параллелизм(подушним чуток)

  • @julik_r
    @julik_r 8 месяцев назад +3

    Спасибо, очень полезно!

  • @МаксимЧерников-х6ц
    @МаксимЧерников-х6ц 8 месяцев назад

    Я наконец то понял, благодаря тебе

  • @programming_etc
    @programming_etc 6 месяцев назад +5

    Ты говоришь правильные вещи, но видимо ты не удосужился запустить собственный код из видео. Конкретно в твоём случае разницы между асинхронным и синхронным кодом вообще не будет)

  • @spike8524
    @spike8524 8 месяцев назад +1

    Полезная инфа)

  • @nouchance
    @nouchance 8 месяцев назад

    Spasibo!

  • @tojiboevqosimjon4226
    @tojiboevqosimjon4226 6 месяцев назад

    Спасибо было очень полезно продолжай в том же духе

  • @Nickola_United
    @Nickola_United 6 месяцев назад +3

    Я может чего-то не понимаю, но дожидаясь ответа с помощью await в основном методе, ты вроде блокируешь его? Чтобы блокировки не происходило, нужно вызвать task.Start() или просто Task.Run(Action)

    • @KirillSachkov
      @KirillSachkov  6 месяцев назад

      Не понимаешь, почитай про async await

    • @Nickola_United
      @Nickola_United 6 месяцев назад +2

      @@KirillSachkov , ну так основной поток вашей программы останавливается после await'а. И где здесь отсутствие блокировки? Объясните пж

    • @Lord_Omni
      @Lord_Omni 6 месяцев назад +1

      @@KirillSachkov await никуда ничего не передаёт, и как раз наоборот до слова await в 11й и 24й строчках всё идёт асинхронно в двух потоках, после чего главный блокируется и ждёт окончания второго, который ждёт окончания третьего, порождённого запросом к гуглу.

    • @programming_etc
      @programming_etc 6 месяцев назад +1

      @@KirillSachkov Понимает, и понимает побольше тебя) Ты бы хоть перед тем как видео выкладывать запустил бы свой код)

    • @КириллМакаричев-п9ю
      @КириллМакаричев-п9ю 6 месяцев назад +7

      И да, и нет. Я бы сказал, что автор не совсем верно указал цель асинхронности. Она обычно нужна в многопользовательских приложениях(проще серверах). Теперь почему. Если все делать синхронно, то все клиенты буду ждать друг друга. То есть придёт 20 запосов, и второй и не начнёт выполняться пока не выполнится первый, третий пока второй и тд до последнего. Но представим, что девятый запрос какой-то супер долгий, тогда получится что 20ый запрос будет ждать девятый, десятый, одиннадцатый и тд. Ооооочень много времени будет ждать этот клиент. Какое может быть решение? Очевидно на первый взгляд Многопоточность, и раньше так к слову и происходило. Как это работает. Теперь для каждого запроса мы выделяем целый поток, этот запрос там работает, не блокируя работу других запросов. Но что может пойти не так? Дотнетовский поток, это обёртка над Виндусовским потоком, поэтому рассмотрим именно его. Стоит сказать, что потоки ос и процессорные потоки не одно и тоже, но для упрощения картины будем рассматривать именно так. В текущих реалиях нормальные процессоры имеют от 6 ядер, серверны от 16, то есть процессор в один квант времени может обработать 16 потоков, но потоков ос гораздо больше(если посмотришь в диспетчер задач увидишь тысячи в разделе процессор). Тут вступает в силу Hyper-threading, который на каждое ядро берет некоторый пул ос потоков и выделяет им квант времени на каждый, создаётся иллюзия что сотни и тысячи потоков работают одновременно, а не только 16. Таким образом мы можем добиться не 16 одновременных запросов, а скажем несколько тысяч псевдо-одновременных. Но как обрабатывать больше. Все просто, делаем псевдо-псевдо-многопоточность, то есть асинхронность. Представим у нас 5 запросов и 1 ядро на машине. Что сделать в наших силах? Первый запрос допустим отправляет запрос в бд, другой запрос на удаленный серв, ещё какой-то считывает данные с диска. Чтобы каждый запрос не ожидал друг друга, сделаем нормальный менеджмент потоками: пока первый запрос идёт в бд, наш вызывающий поток обрабатывает запрос 2, когда он пойдёт на удаленный ресурс, наш поток начнёт работать над третьим потоком и тд. То есть он начнёт работать над всеми запросами, разбив их на маленькие кусочки и на моменте await, просто будет возвращаться в пул, где его может выбрать ос для решения другой задачи. Когда допустим запрос 2 получит ответ, то придёт уведомление в нашу программу, ос выберет поток(не обязательно запускавший таску, но у него будет приоритет) и продолжит задачу.
      Что ещё стоит понимать, обычно работа с асинхронностью имеет смысл когда есть удаленный ресурс (бд, другой серв, или даже жд/ссд диск на нашем компе), то есть должно быть устройство принимающее наш запрос на работу. То есть пока жд будет искать данные в себе, наш поток таким образом не будет простаивать, а будет выполнять другую задачу(это и называется "не блокировать поток") .
      В случае кода автора, поток простаивает и не несёт полезной нагрузки, т.е. не выполняет другую задачу, а значит можно сказать он блокируется "не явно"
      Надеюсь понятно объяснил как на самом деле это работает и для чего нужно)

  • @dnovs_tx
    @dnovs_tx 8 месяцев назад +13

    Фиговое объяснение - обычные люди ни разу не слышали понятия поток, главный поток. Сначала им надо хоть это объяснить, или вообще изменить трактовку, сказав "у нас есть несколько потоков, каждый что-то выполняет, для гибкости (в плане использования памяти) мы имеем главный, на который будем вешать управление (прием, отправку данных и распределение задач) и остальные, которые получают инструкции и данные и соответственно выполняют поставленные задачи"

    • @payrgames
      @payrgames 8 месяцев назад +1

      С твоим комментом понятнее стало

  • @lamenz6840
    @lamenz6840 8 месяцев назад +3

    Может быть ты знаешь, в каких случаях надо писать ConfigureAwait(false)?

    • @KirillSachkov
      @KirillSachkov  8 месяцев назад +1

      Когда нужно, чтобы асинхронная операция завершилась в том потоке, откуда была вызвана

    • @ryanlashkevich9615
      @ryanlashkevich9615 6 месяцев назад +1

      @@KirillSachkov failed

  • @Lord_Omni
    @Lord_Omni 6 месяцев назад +2

    Описание работы - вообще не верное. Как это работает правильными словами: главный поток вызывает таску в строке 1, с этого момента она работает параллельно в другом потоке. Главный поток идёт дальше до 11й строчки и встаёт, дожидаясь окончания работы таски. Сама таска в своём потоке идёт до 24й строки и встаёт, дожидаясь окончания запроса, после чего метод завершается в 26й, второй поток умирает, главный дожидается его окончания и идёт на 13ю.

    • @БотКапот
      @БотКапот 6 месяцев назад +1

      1) Поток непрерывно выполнится до 24 строчки
      2)Тут нет "параллельной работы"
      3) В консольном приложении сказать что "поток умирает" не очень правильно. Есть пул потоков которые обрабатывают таски

  • @СергейКадеев-ф6я
    @СергейКадеев-ф6я 6 месяцев назад

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

  • @егор-ш2о5з
    @егор-ш2о5з 6 месяцев назад

    Ну, это вообще херовое объяснение, оно не даёт понимания людям, которые видят это впервые.
    В данном случае вообще можно обойтись без async/await и абсолютно ничего не поменяется.
    От это был бы какой-то прок только если это было бы GUI приложение или какой-нибудь сервер.
    Async/await в основном используют чтобы выполнять что-то параллельно.

  • @harry_holland
    @harry_holland 4 месяца назад

    че за шляпа