Ребят, тема на подумать, "вы не решайте сгоряча"!
Зачем нам нужна асинхронность? (в контексте GUI программ, взаимодействующих с юзером)
Весь принцип работы юзера — это некий экшн (клик, нажатие) и исполнение средой соотв. команды.
MS просто из кожи вылезла, доказывая нам, какое она "бобро" сотворила, наворотив своих async/await. Даже API везде искорёжила в угоду "новому тренду".
А я вот так смотрю на работу программы и не вижу в этом никакого смысла.
Заметьте — я ничего не говорю про мультипоточность — она нужна, хотя опять же, далеко не везде.
Но вот async?...
Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы!
Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил!
По-моему, даже если команда выполняется "долго" (1+ секунд), нет вообще никакого смысла скрывать её за "отзывчивым интерфейсом", потому что если мы командуем, мы ждём РЕЗУЛЬТАТА команды!
Более того — если подразумевается ещё более долгая работа (5+ секунд), такие действия должны заворачиваться в "диалог прогресса + немедленной отмены". Зачем тут async?
У меня со времён этой "распеаренной асинхронщины" была куча ГУЁВ, я даже пытался что-то наасинхронить (типа "долгая работа с Тырнетом"), но вот факт тот, что ВООБЩЕ НИГДЕ эта асинхронность не лезла!
Если ты работаешь и у тебя проблема, ты НЕ МОЖЕШЬ продолжать работу. Ты должен дождаться результата операции, и только если она успешна — продолжать тыкать куда-то ещё.
Я понимаю, что сейчас высказался всего лишь про собственный опыт (ну а как ещё??), но вот именно опыт и есть та проверка "теории", которая была "гладка на бумаге".
Мне опыт говорит, что это всё переоценённое фуфло. Но если у вас есть прям идеальные случаи под async, не поленитесь, черкните ваш случай!
Спасибо!
UPD
Как и ожидал, несмотря на тонны материалов по thread и async, некоторые до сих пор думают, что это одно и то же.
Здравствуйте, Kolesiki, Вы писали:
K>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы! K>Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил!
Значит, она нужна не везде. Например, проверка орфографии, поиск по документу, всякие тяжёлые операции с картинками и видео, требующие долгой инициализации — всё это может, а то и должно быть асинхронным.
Нажал ты "Подсветка орфографических ошибок". Документ должен подвиснуть, пока загружается модуль орфографии для явзыка и идёт проверка? Кажется, что вообще ничего не должно измениться, работа над документов должна продолжиться, а, когда орфография будет УЖЕ проверена, надо подсветить.
Также работает подсветка синтаксиса в редакторах. Я не хочу, чтобы всё подвисало по мере ввода кода или вставки больших его кусков из одного места в другое. Я хочу редактировать.
Нажал кнопку "Build" — я не хочу подвисания редактора кода, пусть билдится, а я продолжу редактировать.
Я нажимаю "Save" регулярно просто на автомате (Ctrl+S) и не хочу ждать, пока оно сохранится на медленном диске удалённой машины, на которой я сейчас по ssh редактирую код. Я хочу, чтобы текущее состояние сохранилось, а я продолжал.
Я включаю субтитры на видео и не хочу смотреть на подвисшее видео, пока они найдутся, загрузятся и отрендерятся.
В охранном видеонаблюдении включение распознавания чего-нибудь может занимать секунды и десятки секунд, пока нейросеть загрузится с диска и развернётся в видеопамяти. Я тем временем хочу смотреть видео.
Я в браузере отмечаю письма прочитанными: клик, клик, клик. Я хочу кликать на письма со своей скоростью, а не ждать каждый раз, пока придёт команда на сервер и обратно.
...
Здравствуйте, Kolesiki, Вы писали:
K>Зачем нам нужна асинхронность? (в контексте GUI программ, взаимодействующих с юзером)
Обработчики нажатий кнопок не должны блокировать event loop. Юзер нажал Save, нужно заблокировать интерфейс (тем же модальным окном), в отдельном потоке запустить сохранение, дождаться завершения, разблокировать интерфейс/показать уведомление. Ну да, и еще уметь отменить, если юзер нажмет на кнопку "Отмена". Это проще всего реализовать именно через асинхронность.
Здравствуйте, Kolesiki, Вы писали:
K>Но вот async?... K>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы! K>Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил!
1) испортить документ — это логическая ошибка, безотносительно реализации. Это значит, что надеяться на успешный сэйв очевидно, нельзя. Но это не значит, что он не может быть асинхронным.
2) подвиснуть на 30 секунд сохраняя документ не отрисовывая окно — не очень дружественно к пользователю. Это надо решать.
3) не разгребать очередь сообщений вообще в течении 30 секунд и не кооперировать с системой как она просит — это еще одна логическая ошибка, приводящая, к потери данных.
4) async/await лишь помогает/позволяет записать некоторые взаимодействия в их более-менее естественной форме, без зубодробильного ручного маршаллинга вызовов по потокам или превращения кода в рандомный набор кусочков реализаций и коллбэков. Но, вполне естественно, что эта фича не заботится о всех возможных и невозможных логических переходах состояний, коих в UI предостаточно. А что будет, если пока документ сохраняется — мы его изменили и опять нажали сохранение? Это всё вопросы которые программисту нужно решать, но это же не задача async/await. А то так можно и к yield return придраться.
Здравствуйте, Kolesiki, Вы писали:
K>MS просто из кожи вылезла, доказывая нам, какое она "бобро" сотворила, наворотив своих async/await. Даже API везде искорёжила в угоду "новому тренду".
Для операций, которые выполняются объективно долго (сетевые запросы, сложные обработки, та же компиляция и т.п.) это очень удобно, если суть операции не подразумевает, что дальнейшая работа невозможна до ее завершения.
Но в современном софте изрядная часть асихронности — всего лишь костыль, позволяющий замаскировать чудовищные (в сотни-тысячи раз по отношению к разумным) тормоза. Большинство софтостроителей использует готовые библиотеки, которые построены на готовых библиотеках, которые... и т.п., и каждый уровень совершенно не заморачивается оптимизацией, поскольку сам по себе и на топовом железе (а на чем же еще сидеть успешным разработчикам?) он работает вполне приемлемо. Несколько таких слоев — и простейшие операции начинают занимать секунды, потребляя при этом еще и хренову гору памяти. На каком-нибудь мейнстриме с HDD это выглядит настолько тоскливо, что хочется застрелиться. Разгребать завалы уже никто не готов, поэтому выносят обработку в параллельные потоки и даже процессы, под видом модного и эффективного тренда.
Асинхронность нужна прежде всего для серверов.
Тебе не нужно держать поток до получения результата и переключать его, на, что тратится значительное время и память для потока.
Пул потоков работает постоянно и в очереди стоят задачи. При превышении очереди могут дать отлуп.
Для десктопа это прежде всего упростить запуск и ожидание потока например для таймаутов и прочего.
Ну и не морозить гуй. Можно еще чего нибудь запустить
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Тебе не нужно держать поток до получения результата и переключать его, на, что тратится значительное время и память для потока.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, Serginio1, Вы писали:
S>>Тебе не нужно держать поток до получения результата и переключать его, на, что тратится значительное время и память для потока.
ЕМ>Какое переключение Вы имеете в виду?
Переключение между потоками Переключение контекста
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Nuzhny, Вы писали:
N> Например, проверка орфографии
Хм... где именно там нужна асинхронность?
Ты нажимаешь кнопку (а вернее, "чекбокс" режима орфиграфии), он мгновенно включает проверку в отдельном потоке, GUI снова в работе!
N> поиск по документу
Опять не вижу места для async. У тебя есть поле поиска и ты ввёл подстроку. Если это поиск в текущем документе — он и так быстрый, находит первое совпадение — всё, работай. ЗАЧЕМ тебе "поиск", если ты не ждёшь первого совпадения??
А если поиск долгий, он вообще делается в отдельном потоке и ГУЮ скармливаются результаты.
N> всякие тяжёлые операции с картинками и видео, требующие долгой инициализации — всё это может, а то и должно быть асинхронным.
...и опять неверно! НЕТ там места для async! Есть место для трэдов, которые очевидно создаются за мгновения.
N>Также работает подсветка синтаксиса в редакторах.
Нет, не "так же". Подсветка может базироваться на эвристиках. Плюс, подсветка никогда не делается "по нажатию", а только по прошествии таймаута (когда чел перестал модифицировать документ). И опять, там вопрос ДАЛЕКО не в async, а быстром снэпшоте документа, его анализе и последущей подсветке.
N>Нажал кнопку "Build" — я не хочу подвисания редактора кода, пусть билдится, а я продолжу редактировать.
И опять это thread, а не async!
N>Я нажимаю "Save" регулярно просто на автомате (Ctrl+S) и не хочу ждать
Не хочешь, а ДОЛЖЕН. Просто потому, что нажатие не гарантирует, что у тебя не отвалился драйв или что-то сломалось.
N>Я включаю субтитры на видео и не хочу смотреть на подвисшее видео, пока они найдутся, загрузятся и отрендерятся.
это thread, а не async
N>Короче, я за асинхронность.
Короче, ВСЕ твои перечисленные случаи вообще не про асинхронность — как и многие начинающие, ты её напрочь перепутал с мультипоточностью.
Здравствуйте, scf, Вы писали:
scf>Здравствуйте, Kolesiki, Вы писали:
K>>Зачем нам нужна асинхронность? (в контексте GUI программ, взаимодействующих с юзером)
scf>Обработчики нажатий кнопок не должны блокировать event loop. Юзер нажал Save, нужно заблокировать интерфейс (тем же модальным окном), в отдельном потоке запустить сохранение, дождаться завершения, разблокировать интерфейс/показать уведомление. Ну да, и еще уметь отменить, если юзер нажмет на кнопку "Отмена". Это проще всего реализовать именно через асинхронность.
Ну так в том и прикол, что показывая модальное окно, ты переносишь активную обработку сообщений В ДРУГОЕ ОКНО! Кому какое дело, как нажата кнопка, если она всё равно заблокирована от взаимодействия и сейчас мы ждём экшенов в модальном окне??
Здравствуйте, Kolesiki, Вы писали:
K>Короче, ВСЕ твои перечисленные случаи вообще не про асинхронность — как и многие начинающие, ты её напрочь перепутал с мультипоточностью.
Ха!
кто тут ещё начинающий. потоки — это один из способов сделать асинхронность. Типа до async её не существовало? Подержи моё пиво.
Здравствуйте, Mystic Artifact, Вы писали:
MA>Здравствуйте, Kolesiki, Вы писали:
K>>Но вот async?... K>>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы! K>>Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил!
MA> 1) испортить документ — это логическая ошибка, безотносительно реализации. Это значит, что надеяться на успешный сэйв очевидно, нельзя. Но это не значит, что он не может быть асинхронным.
Он может быть каким угодно, я спросил про асинк — каким боком он мне поможет, если я не знаю результата операции??
И напоминаю, сэйвы в отдельном потоке никто не отменял.
MA> 2) подвиснуть на 30 секунд сохраняя документ не отрисовывая окно — не очень дружественно к пользователю. Это надо решать.
Никто не говорил про "не отрисовывая". Забудьте про этот атавизм! Давно придуманы потоки, корутины, таски и т.п.
MA> 4) async/await лишь помогает/позволяет записать некоторые взаимодействия в их более-менее естественной форме, без зубодробильного ручного маршаллинга вызовов по потокам
В теории — да. Но как я показал, от того, что кнопка сразу "отжалась", легче никому не стало — ты всё равно обязан либо иметь механизм ожидания долгой операции, либо тупо подождать её завершения, ибо от неё зависит последущая работа (это не только про сэйв).
Здравствуйте, Serginio1, Вы писали:
S>Для десктопа это прежде всего упростить запуск и ожидание потока например для таймаутов и прочего. S>Ну и не морозить гуй. Можно еще чего нибудь запустить
ГУЙ и так не будет тормозить — вам что, потоков мало? Таймауты — аналогично.
Здравствуйте, Nuzhny, Вы писали:
N>Здравствуйте, Kolesiki, Вы писали:
K>>Короче, ВСЕ твои перечисленные случаи вообще не про асинхронность — как и многие начинающие, ты её напрочь перепутал с мультипоточностью.
N>Ха! N>кто тут ещё начинающий. потоки — это один из способов сделать асинхронность. Типа до async её не существовало? Подержи моё пиво.
Сам держи своё пойло, школота! Ты ещё и термины напрочь перепутал.
Речь о том, что async/await (которые как бы смахивают на асинхронность, но которые НЕ ЯВЛЯЮТСЯ параллельным исполнением) нафиг не нужны. По кр. мере ты не показал НИ ОДНОГО случая, когда они необходимы.
Практически все случаи абсолютно спокойно разруливаются трэдами или легковесными тасками.
Здравствуйте, Serginio1, Вы писали:
ЕМ>>Какое переключение Вы имеете в виду? S>Переключение между потоками S>Переключение контекста
О том, что переключение контекста занимает "значительное время", было уместно говорить лет двадцать назад, когда железо было в несколько раз медленнее, а софт — в сотни раз менее тормозным. Для того, чтобы воообще как-то заметить накладные расходы на переключение контекста, его нужно переключать минимум несколько тысяч раз в секунду. Чтобы эти расходы стали заметны на фоне прикладного кода, этот код должен быть идеально вылизан, чего нынче почти встречается. Ну а затраты памяти на поток, по нынешним меркам, и вовсе ничтожны. При современном размашистом подходе к разработке софта, о накладных расходах на потоки имеет смысл начинать думать не раньше, чем количество потоков в приложении достигнет нескольких сотен.
Здравствуйте, Kolesiki, Вы писали:
K>Но вот async?... K>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы! K>Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил!
... K>Мне опыт говорит, что это всё переоценённое фуфло. Но если у вас есть прям идеальные случаи под async, не поленитесь, черкните ваш случай!
async/await это не для асинхронных методов, а для языковой поддержки многозадачности.
В результате вместо кучи приседаний с воркерами, потоками и прочей низкоуровневой болтовнёй получаешь нечто навроде
Надо — жди. Не надо — не жди. Зато незачем городить огород из воркеров, передавать им параметры в очередь и заниматься прочими глупостями.
Фактически при помощи этих примитивов очень легко вытеснить тяжелый процессинг в другой вычислитель.
Скажем, при некоторых параметрах(консольное исполнение) выполняем и ждем по месту, а при других параметрах(ui, сервер и тд) — вытесняем куда угодно, абы не мешало. Код от этого меняться не должен.
Здравствуйте, Kolesiki, Вы писали:
K>Здравствуйте, Serginio1, Вы писали:
S>>Для десктопа это прежде всего упростить запуск и ожидание потока например для таймаутов и прочего. S>>Ну и не морозить гуй. Можно еще чего нибудь запустить
K>ГУЙ и так не будет тормозить — вам что, потоков мало? Таймауты — аналогично.
Ну их отдельно нужно запускать. Неудобно, я же написал
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Kolesiki, Вы писали:
K>Он может быть каким угодно, я спросил про асинк — каким боком он мне поможет, если я не знаю результата операции?? K>И напоминаю, сэйвы в отдельном потоке никто не отменял.
await. Если же ты нигде не ждешь завершения операции — очевидно, это ошибка. А поэтому, твой вопрос теряет смысл.
K>Никто не говорил про "не отрисовывая". Забудьте про этот атавизм! Давно придуманы потоки, корутины, таски и т.п.
Ну так async это тот же таск. Если сахар не нужен — то его и не обязательно использовать.
K>В теории — да. Но как я показал, от того, что кнопка сразу "отжалась", легче никому не стало — ты всё равно обязан либо иметь механизм ожидания долгой операции, либо тупо подождать её завершения, ибо от неё зависит последущая работа (это не только про сэйв).
Разница только в том, что с async/await можно с концентрировать логику действия в одном месте, а с помощью классических подходов, которые, безусловно работают — она стремится разползтись не только по разным методам, но и по модулям. Классические event-driven решения — это чаще всего — тихий ужас, потому что работает это не системно.
Если ты можешь удержать в голове и увязать вместе пару десятков состояний — поздравляю, ты молодец. Но код будет — непонятное говно.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, Serginio1, Вы писали:
ЕМ>>>Какое переключение Вы имеете в виду? S>>Переключение между потоками S>>Переключение контекста
ЕМ>О том, что переключение контекста занимает "значительное время", было уместно говорить лет двадцать назад, когда железо было в несколько раз медленнее, а софт — в сотни раз менее тормозным. Для того, чтобы воообще как-то заметить накладные расходы на переключение контекста, его нужно переключать минимум несколько тысяч раз в секунду. Чтобы эти расходы стали заметны на фоне прикладного кода, этот код должен быть идеально вылизан, чего нынче почти встречается. Ну а затраты памяти на поток, по нынешним меркам, и вовсе ничтожны. При современном размашистом подходе к разработке софта, о накладных расходах на потоки имеет смысл начинать думать не раньше, чем количество потоков в приложении достигнет нескольких сотен.
For a small number of concurrent requests (100), synchronous and asynchronous results were pretty close, with 47/48 requests per second and 2065/2027 median latency. The difference was more drastic for 1000 concurrent requests, with sync attaining 65 req/s and 10507 ms median latency, and async attaining 98.86 req/s and 10080 ms, with significantly lower latency deviation (1506 ms vs 8000 ms). I have not seen any failed requests at all.
At the moment I am not able to test more than 1000 requests for unknown reason, and my machine is a humble Pentium E6800 with 6GB of memory running Windows 7.