Здравствуйте, Kolesiki, Вы писали:
K>Зачем нам нужна асинхронность? (в контексте GUI программ, взаимодействующих с юзером)
Хочешь продолжать делать это вручную вместо API?
K>Весь принцип работы юзера — это некий экшн (клик, нажатие) и исполнение средой соотв. команды.
Не-а. Юзеры ещё фапают. Причём доля фапа может быть сильно больше экшена. Из-за ржавых мозги, или просто программа умеет отвлечь привлечь внимание пользователя.
Попытка программы украсть у пользователя его священное право на тупи/тормози наказуема через удаление программ.
K>Но вот async?...
Что, неприятное слово?
K>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы!
Нет так, как пользователь пишу. Ты нажал Save, заказал действие, и продолжил свои дела. Ты ожидаешь, что программа не мешая тебе сохранит состояние на момент нажатия save и уведомит тебя. Фапать на save ты уже можешь, но вот возможость продолжать работать бесценна.
K>Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил!
Так всё дело в пузырьках! Где дизайнер, обеспечивший "состояние сохранения" и возможность выбора другого файла/диска/сети, многократную реентерабельность операции и её повторение? Профукал, да?
Чтобы уведомить пользователя, не обязательно модалить окна и противно бипать на мышку, в тех же играх давно есть всплывающие вверх панельки вдоль стороны экрана с информированием об отложенных событиях.
K>Если ты работаешь и у тебя проблема, ты НЕ МОЖЕШЬ продолжать работу. Ты должен дождаться результата операции, и только если она успешна — продолжать тыкать куда-то ещё.
Чегойто? Какойто?
На дворе 2020 год. Программы не только должны показывать проблемы, но и предлагать решения. А уж падение программ несерьёзно уже с 16 бит.
У тебя мозг когда сталкивается с проблемой, ты дышать перестёшь? А думать? А родных вспоминать? Вот и программам пора повзрослеть.
Программа должна предусматривать реакцию на возможные проблемы. А не "а, я обломилась, хороните меня, звоните Биллу Гейтсу, на Московский вентиляторный завод".
K>Как и ожидал, несмотря на тонны материалов по thread и async, некоторые до сих пор думают, что это одно и то же.
Так это другая проблема, проблема правильной подачи документации. Раньше открываешь функцию API, там тебе и смысл, и описание параметров, и типичные сценарии, и примеры, и перекрёстные ссылки.
Здравствуйте, Kolesiki, Вы писали:
K>Зачем нам нужна асинхронность? (в контексте GUI программ, взаимодействующих с юзером)
Ты, пожалуйста, не путай асинхронность, как возможность сделать долгую операцию в фоне, не блокируя весь пользовательский интерфейс, и async/await, как метод реализации этой асинхронности, который ты зачем-то противопоставляешь потокам.
Использование async/await или потоков — это вопрос архитектурный. И то и другое имеет свои достоинства и недостатки.
Возможность запустить долгую операцию в фоне — это вопрос удобства пользовательского интерфейса. Эти две вещи вообще лежат в разных плоскостях.
K>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы!
Ну так с умом надо использовать-то. Понятно, что если у тебя save долгий, да еще и не ясно, чем кончится, то все изменениия в том "документе", который ты сохраняешь, должны быть заблокированы до завершения save. По крайней мере, если ты не собираешься реализовывать сложную логику трехсторонней синхронизации между тем, что у тебя на самом деле на диске, тем, что пользователь думает, что у него на диске, и тем, что у пользователя на экране.
Имхо, самая польза асинхронности, это иметь отдельные "логические" потоки управления, которые иначе пришлось бы делать на макаронах из колбэков.
Допустим, пользователь хочет что-то сделать, но чтобы сделать вы просите пользователя что-то выбрать на, допустим, чертеже. И ждете.
Далее в зависимости от того, что выбрано просите выбрать еще раз/что-то другое/...
Замените ожидание действия пользователя на ожидание другой долгой операции.
Здравствуйте, Kolesiki, Вы писали:
...
Есть понятие "асинхронность", и есть механизмы реализации этого понятия.
Многопоточность — это один из механизмов реализации асинхронности.
Ранее, ЕМНИП во времена Windows 3.11, понятие "асинхронность" не реализовывалось через multi-threading.
Тогда были специальные "асинхронные" реализации. Которые, ради совместимости, существуют и по сей день (но реально уже давно не используются).
Теперь (последние лет 20-ть): асинхронность реализуется через multi-threading.
Это намного удобнее и рациональнее, нежели набор "асинхронных" методов.
... K>Практически все случаи абсолютно спокойно разруливаются трэдами или легковесными тасками.
Но возникают проблемы синхронизации потоков выполнения (thread-ов)...
Здравствуйте, Kolesiki, Вы писали:
K>Ну так в том и прикол, что показывая модальное окно, ты переносишь активную обработку сообщений В ДРУГОЕ ОКНО! Кому какое дело, как нажата кнопка, если она всё равно заблокирована от взаимодействия и сейчас мы ждём экшенов в модальном окне??
Мы можем сделать отдельный (рабочий) поток и в этом окне. И как-правило делаем его.
В противном случае, это окно будет "замораживаться" при длительных расчётных операциях.
Можно также и "прокачивать_сообщения" OS — чтобы не было "замораживания" элементов GUI.
P.S. Локального сохранения (в файл) это не касается, если файл не совсем гигантского размера, а вот для работы с далеким серваком — это будет в тему.
Здравствуйте, Serginio1, Вы писали:
S>Там не то что сотни, сотни тысяч запросов в секунду. Заметь я писал про сервера.
Угу. Только вот код, оптимизированный настолько, чтобы на его фоне стало критично время переключения контекста, подавляющее большинство нынешних программистов (включая и большинство тех, кто пишет для серверов) написать не сможет.
S>
The difference was more drastic for 1000 concurrent requests>
Тысяча запросов в секунду на современном железе может упереться в затраты на переключение контекста лишь в том случае, если при обработке каждого запроса контекст будет переключаться минимум несколько сотен раз, что в первую очередь означает явную кривизну кода. То есть, первым делом нужно исправлять кривой алгоритм.
S>Кроме того скоро наступает эпоха IoT и лишними ресурсы не бывают
Да ни фига, это уже проходили на смартфонах. Поначалу, с подачи гугловской документации, порывались экономить, но быстро поняли, что плодить ядра, гигагерцы и гигабайты технически проще. Экономить начнут не раньше, чем добавление даже 20% скорости или объема станет выливаться в неприемлемые затраты.
ЕМ>Тысяча запросов в секунду на современном железе может упереться в затраты на переключение контекста лишь в том случае, если при обработке каждого запроса контекст будет переключаться минимум несколько сотен раз, что в первую очередь означает явную кривизну кода. То есть, первым делом нужно исправлять кривой алгоритм.
То есть цифры тебя не переубеждают? S>>Кроме того скоро наступает эпоха IoT и лишними ресурсы не бывают
ЕМ>Да ни фига, это уже проходили на смартфонах. Поначалу, с подачи гугловской документации, порывались экономить, но быстро поняли, что плодить ядра, гигагерцы и гигабайты технически проще. Экономить начнут не раньше, чем добавление даже 20% скорости или объема станет выливаться в неприемлемые затраты.
Я привел тебе примеры того, что асинхронный код увеличивает производительность на серверах с количеством запросов больше 100.
Можно сделать тестовый сервер и запросы к БД на другой (их) машинах как это правило и делается, можно с редисом для кэширования. И посмотреть сколько запросов можно обрботать.
Ну и IoT это далеко не смартфоны. Это могут быть типа raspberry pi
и солнце б утром не вставало, когда бы не было меня
Судя по дальнейшему обсуждению, автор темы немного ошибся в терминологии. Похоже что он хотел обсудить полезность такой конкретной технологии, как async/await в .net, а зацепил всю огромную тему асинхронности, которая имеет множество применений в разных областях и в разных реализациях (в том числе и банальными системными потоками).
Так вот, если говорить о async/await в .net, то это полезный инструмент ровно для одной цели — для превращения обычно некрасивого кода работы с асинхронным вводом-выводом в его красивый (похожий на синхронный аналог) вариант. А вот асинхронный ввод-вывод в свою очередь полезен ровно в одном случае — если нам необходимо держать одновременно более 1000 параллельных задач (в этом случае синхронный ввод-вывод, требующий вытесняющую многозадачность уже не справляется с адекватным переключением контекстов). Т.е. в итоге async/await — это полезный инструмент для улучшения читаемости кода, правильно написанных высоконагруженных сервисов. В принципе больше ни для чего полезного он не подходит, так что если встречается где-то ещё, то это обычно проявление классического синдрома слабых программистов, нашедших очередную серебряную пулю.
Ну а просто асинхронность (без всяких там async/await, а в абстрактном понимание этого термина, в том числе и в виде запуска отдельного потока с тяжёлыми синхронными запросами) — это естественно абсолютно вездесущая концепция, которая нужна всегда и везде.
Здравствуйте, alex_public, Вы писали:
_>Так вот, если говорить о async/await в .net, то это полезный инструмент ровно для одной цели — для превращения обычно некрасивого кода работы с асинхронным вводом-выводом в его красивый (похожий на синхронный аналог) вариант.
Не согласен с далеко-идущими выводами по поводу ограниченности применения, в плане про тысячи и зиллиарды коннектов и только ввода-вывода.
Сегодня даже в скромных клиентских приложениях происходит асинхронная обработка данных: иногда это связано с кросс-процессным взаимодействием, иногда с естественными потребностями или даже ограничениями платформы (на подобии браузера/javascript). Тут нет места для тысяч одновременных коннектов, но вполне есть место для async/await.
Операции могут быть просто CPU-bound и проводить значительное время, или, проводить непредсказуемое время, потому что внутри есть кеширующий слой, а доступ к кешу, на том же диске — может быть не бесплатен. Тут не важно, как оно устроено внутри, а важно что мы можем это красиво и понятно записать, не запутавшись в 3 соснах. В добавок это инструмент ограниченной параллелизации, когда это возможно задачей или поддерживается структурами данных.
Безусловно — тыкать везде подряд это пожалуй не стоит. Есть тыща и одна задача которая не очень любит распараллеливается или это просто не нужно.
Но так ты правильно же говоришь — инструсент, он полезен, и хорошо, что есть.
K>Как и ожидал, несмотря на тонны материалов по thread и async, некоторые до сих пор думают, что это одно и то же.
Могу ошибаться, поправьте.
Раньше асинхронные вызовы не создавали дополнительных потоков.
И делались они, в основном, для записи и чтения.
В потоке окна писали пакет размером с предполагаемый буфер.
Затем цикл обработки сообщений окна продолжал работу, периодически проверяя ответ от железяки.
Все это внутри самой Windows было.
Те был один поток и при этом окно не подвисало при чтении/записи.
Но считать, перебирать, сортировать там нельзя было категорически.
Вроде, я где-то читал при появлении asyn-await, что он реализован именно так. Или так только задумывалось.
По факту создаются потоки. И как-то синхронизируются с основным потоком.
Но это уже не та асинхронность без лишних потоков в ожидании. Любо Windows нам так их показывает.
Здравствуйте, namespace, Вы писали:
N>Могу ошибаться, поправьте. N>Раньше асинхронные вызовы не создавали дополнительных потоков. N>И делались они, в основном, для записи и чтения.
Как сделать вызов, всегда решаешь ты сам. Да, в дотнете — по умолчанию все идет на пул потоков. И то, по сути все под контролем на стороне и вызывающего и реализующего. Вместе с тем, там есть и контексты синхронизации, которые необходимы как и для любых UI фреймворков, так и для IIS / ASP.NET (где твои методы контроллеров уже вызываются на пуле потоков, не дотнетном и ты можешь или заблокировать поток (чем изрядно уменьшить реальную достижимую нагрузку), или сделать await на его контексте синхронизации без ConfigureAwait(false)) и это все равно вызывало кучу проблем. В современном хосте и/или иных хостах вокруг дотнет коры — там все идет на пул потоков, и париться не надо.
N>В потоке окна писали пакет размером с предполагаемый буфер. N>Затем цикл обработки сообщений окна продолжал работу, периодически проверяя ответ от железяки. N>Все это внутри самой Windows было.
Цикл обработки сообщений обычно "живет" в основном потоке процесса. Это не эфемерный код со стороны — это клиентский код который содержит любая Win32 программа. Когда "окно" получает сообщение — это результат вызова в этом самом потоке DispatchMessage.
N>Те был один поток и при этом окно не подвисало при чтении/записи. N>Но считать, перебирать, сортировать там нельзя было категорически.
Так же само сейчас. На всех основных платформах.
N>Вроде, я где-то читал при появлении asyn-await, что он реализован именно так. Или так только задумывалось.
Пул потоков / библиотека TPL кооперативно разребает накопленные задачи, таким образом не теряя время на синхронизацию/или переключения.
N>По факту создаются потоки. И как-то синхронизируются с основным потоком.
В хроме кроме пула потоков, есть еще специальные потоки: UI, IO, File (blocking) и т.п. — в них сидят такие же самые циклы обработки сообщений. Но, попытки вызова методов не на тех потоках всегда больно бьет по рукам. Это с одной стороны дисциплинирует, с другой стороны вводит дохрена неявности, потому что "этот метод может быть вызван на любом потоке" как правило означает "я проверяю на каком потоке я и маршалю вызов на другой поток, но когда он завершится — спросите у void".
N>Но это уже не та асинхронность без лишних потоков в ожидании. Любо Windows нам так их показывает.
Web, TypeScript — чистая однопоточность, тот же самый async/await. Раньше приходилось костыли изобретать, весьма неудобные.
UPD: Это галопом по галактике, очень грубо. Я едва понял что ты там написал.
Здравствуйте, Kolesiki, Вы писали:
K>Ребят, тема на подумать, "вы не решайте сгоряча"! K>Зачем нам нужна асинхронность? (в контексте GUI программ, взаимодействующих с юзером) K>Весь принцип работы юзера — это некий экшн (клик, нажатие) и исполнение средой соотв. команды. K>MS просто из кожи вылезла, доказывая нам, какое она "бобро" сотворила, наворотив своих async/await. Даже API везде искорёжила в угоду "новому тренду".
Вот хотелось бы знать что так возмущает. Если задача упирается в сеть или диск — async/await именно то что доктор прописал.
K>А я вот так смотрю на работу программы и не вижу в этом никакого смысла. K>Заметьте — я ничего не говорю про мультипоточность — она нужна, хотя опять же, далеко не везде. K>Но вот async?... K>Пусть это будет команда Save. Мы нажали, асинхронно вышли из метода, куда-то даже полезли нажимать другие команды, а save всё ещё работает! Хуже того — у неё могут возникнуть проблемы! K>Ну и вот какой смысл "не ждать завершения команды", если всё равно тебе прилетит по лбу? Хуже того — ты понадеялся на УСПЕШНЫЙ сэйв, а документ уже испортил! K>По-моему, даже если команда выполняется "долго" (1+ секунд), нет вообще никакого смысла скрывать её за "отзывчивым интерфейсом", потому что если мы командуем, мы ждём РЕЗУЛЬТАТА команды! K>Более того — если подразумевается ещё более долгая работа (5+ секунд), такие действия должны заворачиваться в "диалог прогресса + немедленной отмены". Зачем тут async?
По-моему ты читал и не дочитал. Метод надо писать с умом. Примерно так (я UI слава богу давно не занимаюсь, так что не обессудьте)
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
if (_isSaving)
return;
// Да хоть кнопку дизейбли или другие части интерфейса зависящие от этого функционала или прогрес крути в статус баре с Cancel
_isSaving = true;
try
{
await SaveMethodAsync(yourCancellationTockenSource.Token);
await DoSomethingElseAsync(yourCancellationTockenSource.Token);
MessageBox.Show("I am done!");
}
finally
{
_isSaving = false;
}
}
Чтобы написать подобное без асинков тебе бы пришлось городить цепочку калбеков — удачи если ты это любишь
K>У меня со времён этой "распеаренной асинхронщины" была куча ГУЁВ, я даже пытался что-то наасинхронить (типа "долгая работа с Тырнетом"), но вот факт тот, что ВООБЩЕ НИГДЕ эта асинхронность не лезла! K>Если ты работаешь и у тебя проблема, ты НЕ МОЖЕШЬ продолжать работу. Ты должен дождаться результата операции, и только если она успешна — продолжать тыкать куда-то ещё.
У тебя каой-то свосем ограниченный UI. Да дизейбли все нафик, но чтобы винда знала что ты жив. На закрытии окна дергай yourCancellationTockenSource.Cancel — решение влоб не думая.
K>Я понимаю, что сейчас высказался всего лишь про собственный опыт (ну а как ещё??), но вот именно опыт и есть та проверка "теории", которая была "гладка на бумаге". K>Мне опыт говорит, что это всё переоценённое фуфло. Но если у вас есть прям идеальные случаи под async, не поленитесь, черкните ваш случай! K>Спасибо!
Про UI не скажу, хотя смотрится тоже норм. Но вот на бакенде вещь просто незаменимая, если конечно у тебя не два-три пользователя только. На 10-и потоках можно спокойно обслужить сотни, а то и тысячи одновременных запросов если они, например, работают с базой.
Здравствуйте, AlexGin, Вы писали:
AG>Мы можем сделать отдельный (рабочий) поток и в этом окне. И как-правило делаем его.
Не в обиду, но окно имеет весьма специфическую связь с потоком. С точки разгребания сообщений — тут скорее поток владеет окном. ADD: Я в не обиду, имел ввиду, что вы с колесиком наперегонки начали перлы выдавать в подветке. Я еле понял что ты имел ввиду. Глаз ухватился за первое предложение и не захотел понимать дальше.
AG>Можно также и "прокачивать_сообщения" OS — чтобы не было "замораживания" элементов GUI
Безусловно. Более того в некотором смысле многие так и работают миксируя несколько очередей сообщений в одном цикле сообщений (нестандартном). Но практической сути это не меняет. Проблема только неоптимальности.
AG>P.S. Локального сохранения (в файл) это не касается, если файл не совсем гигантского размера, а вот для работы с далеким серваком — это будет в тему.
На самом деле это касается исключительно любого IO. Достаточно вставить в системник битый хард и часто можно будет наблюдать что некоторые приложения крайне жестко залипают, в то время как, тот же какой-нибудь злополучный хром — спокойно грузится как не бывало и браузит интернет, и его не волнует, что диск без буквы неожиданно притупил половину приложений. (Понятно, что как повезет, но думаю, идея понятна).
Здравствуйте, Danchik, Вы писали:
D>По-моему ты читал и не дочитал. Метод надо писать с умом. Примерно так (я UI слава богу давно не занимаюсь, так что не обессудьте)
Для полной красоты не хватает только какого-нибудь scope-based/disposable трэкера занятости, ну типа часики или даже окно с тем, что операция продолжается и/или с прогрессом. При чем в нем может быть реализован и таймаут когда это начать показывать. В целом то идея очень не новая, ну я просто к примеру, где это тоже может легко вписаться.
_>Ну а просто асинхронность (без всяких там async/await, а в абстрактном понимание этого термина, в том числе и в виде запуска отдельного потока с тяжёлыми синхронными запросами) — это естественно абсолютно вездесущая концепция, которая нужна всегда и везде.
Здравствуйте, Mystic Artifact, Вы писали:
_>>Так вот, если говорить о async/await в .net, то это полезный инструмент ровно для одной цели — для превращения обычно некрасивого кода работы с асинхронным вводом-выводом в его красивый (похожий на синхронный аналог) вариант. MA> Не согласен с далеко-идущими выводами по поводу ограниченности применения, в плане про тысячи и зиллиарды коннектов и только ввода-вывода. MA> Сегодня даже в скромных клиентских приложениях происходит асинхронная обработка данных: иногда это связано с кросс-процессным взаимодействием, иногда с естественными потребностями или даже ограничениями платформы (на подобии браузера/javascript). Тут нет места для тысяч одновременных коннектов, но вполне есть место для async/await.
Согласен, что в случае JS раньше (сейчас то уже есть Web Workers API) было такое ограничение и единственным средством организации параллельного выполнения в JS были асинхронные вызовы (не важно обёрнутые в сопрограммы или же просто в виде коллбэков). Но в наше время уже даже в JS такого не требуется.
MA> Операции могут быть просто CPU-bound и проводить значительное время, или, проводить непредсказуемое время, потому что внутри есть кеширующий слой, а доступ к кешу, на том же диске — может быть не бесплатен. Тут не важно, как оно устроено внутри, а важно что мы можем это красиво и понятно записать, не запутавшись в 3 соснах. В добавок это инструмент ограниченной параллелизации, когда это возможно задачей или поддерживается структурами данных.
А вот для этих целей запуск отдельных потоков (с использованием внутри них синхронных операций) точно будет правильнее. Не нужен тут ни асинхронный ввод-вывод, ни сопрограммы.
MA> Безусловно — тыкать везде подряд это пожалуй не стоит. Есть тыща и одна задача которая не очень любит распараллеливается или это просто не нужно.
Я тут говорил как раз не про задачи, которые плохо распараллеливаются. А скорее про задачи, для распараллеливания которых правильнее применять более адекватные инструменты.
1) Есть файл. Размер... ну пусть 100 мб. В файле находится 100К записей. У каждой записи — есть ассоциированный сжатый deflate блок.
2) Задача — загрузить файл максимально быстро и распаковать данные. Памяти при этом требуется 300-400Мб.
Задача, в принципе тривиальная и хорошо распаралеливается.
Попытка использования асинков для чтения файла — оказалась фейлом. Оно выполняется не быстрее.
После некоторых ковыряний в коде, что сеттер FileStream.Position = position, если он уже на этой позиции выполняет какие-то охеренческие манипуляции с буфером. Доступ фактически последовательный, и хотелось его сохранить таким.
И вот распараллеливание:
1) либо открыть несколько стримов на файл и херячить как получится (как-то некузяво)
2) читаем сжатые блоки последовательно — распаковываем в потоках:
2.а) Parallel.For — либо не может буферизирует IEnumerable агрессивно (128 * 4) либо по одному — либо мы создаем 30К буферов либо тупо голодаем
2.б) Параллельно понимаем, что только server gc может обеспечить 100% загрузку CPU
2.в) пишем простой producer-consumer (на BlockingCollection) с bound processor count * 2..4 и консюмеров создаем тупо на пуле которые разребают. Временных буфферов реально максимум штук 300 и 100% загрузка CPU с адекватной временной характеристикой. (workstation gc грузит про на 60% и делает сборок мусора фантастическое кол-во по сравнению с сервером (160 vs 2)), при чем смешно — серверный GC имеет наименьший пик по выделенной памяти.
2.г) выкидываем никудышний DeflateStream (zlib) и меняем на ориентированный на буфера — libdeflate: время еще скоращается, и ненужных аллокаций становится еще раза в 3 меньше.
TPL — использован. await/async места не нашлось. Но — при любом движняке можно легко переделать и на асинки. код компактен. А по сути, я вообще не думал это делать, сначала тыкнулся случайно в Parallel.For и показалось тут оно легко ляжет. Легко не лягко. Есть подобный файл но с LZ4, там до смешного — оно в одном потоке делает так быстро что манипуляции с их кучей они и не нужны (но уже есть, не отказываться же).
Задачка в принципе делалась для фана, но просто как пример, что в этой всей многопоточности есть куча решений, и скажем, если бы какие-то средства отсутствовали бы в фреймворке — яб и не парился вовсе.
Здравствуйте, Danchik, Вы писали:
D>Вот хотелось бы знать что так возмущает. Если задача упирается в сеть или диск — async/await именно то что доктор прописал.
Ну вот простейшая классическая задача: скопировать файл (читаем его в буфер в памяти и параллельно записываем на диск в новое место). Эта задача собственно вот только в диск и упирается. И ты реально считаешь, что для её реализации будут эффективнее сопрограммы с асинхронным вводом-выводом? )))
D>По-моему ты читал и не дочитал. Метод надо писать с умом. Примерно так (я UI слава богу давно не занимаюсь, так что не обессудьте) D>
D>private async void btnSave_Click(object sender, RoutedEventArgs e)
D>{
D> if (_isSaving)
D> return;
D> // Да хоть кнопку дизейбли или другие части интерфейса зависящие от этого функционала или прогрес крути в статус баре с Cancel
D> _isSaving = true;
D> try
D> {
D> await SaveMethodAsync(yourCancellationTockenSource.Token);
D> await DoSomethingElseAsync(yourCancellationTockenSource.Token);
D> MessageBox.Show("I am done!");
D> }
D> finally
D> {
D> _isSaving = false;
D> }
D>}
D>
D>Чтобы написать подобное без асинков тебе бы пришлось городить цепочку калбеков — удачи если ты это любишь
Или же просто запустить эту операцию в отдельном потоке. ))) Что будет намного проще и эффективнее.
D>Про UI не скажу, хотя смотрится тоже норм. Но вот на бакенде вещь просто незаменимая, если конечно у тебя не два-три пользователя только. На 10-и потоках можно спокойно обслужить сотни, а то и тысячи одновременных запросов если они, например, работают с базой.
Вот, здесь уже всё сказано корректно (ну разве что apache на потоках держал всё же побольше 2-3 пользователей). Только вот ты как-то забываешь, что основной сценарий из мира бэкенда, является вырожденным практически во всех остальных областях.
Здравствуйте, Serginio1, Вы писали:
S> То есть цифры тебя не переубеждают?
Я пока не понял, какое эти цифры имеют отношение к переключению контекста между потоками.
S>Я привел тебе примеры того, что асинхронный код увеличивает производительность на серверах с количеством запросов больше 100.
Насколько я понимаю, там речь идет о высокоуровневых API, которые сами по себе весьма толсты и неуклюжи, и где почти любая оптимизация способна дать ощутимый эффект.
S>Ну и IoT это далеко не смартфоны. Это могут быть типа raspberry pi
У которой частота порядка гигагерца, и памяти минимум 256 Мб, а делается на ней в основном то же самое, для чего раньше хватало единиц мегагерц и десятков-сотен килобайт.
Здравствуйте, Kolesiki, Вы писали:
K>Ну так в том и прикол, что показывая модальное окно, ты переносишь активную обработку сообщений В ДРУГОЕ ОКНО! Кому какое дело, как нажата кнопка, если она всё равно заблокирована от взаимодействия и сейчас мы ждём экшенов в модальном окне??
Да, всё так. Но на асинхронщине это делать удобнее, когда привыкнешь. И даже если скилл запуска асинхронных задач в отдельном потоке оттчен до совершенства, переходить на async все равно придется, чтобы не отстать от жизни.