|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Давно тут смотрю ConfigureAwait не обсуждалось ))) Есть клиентское WPF приложение, приведена его MVVM модель (упрощенный вариант). В модели есть команда (привязанная к кнопке), обработчик которой дергает два асинхронных метода модели, которые в свою очередь дергают асинхронные методы WCF клиента. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51.
Я в курсе про контексты и как это работает. Интересно именно в контексте данного примера: 1) имеет ли смысл в данном коде использовать .ConfigureAwait в таком виде как они приведены в примере? если да то в чем будет профит? (кроме того что успокоится анализатор кода) 2) может есть варианты как-то более правильно .ConfigureAwait(false) в таком коде применить? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2020, 15:18 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Нужен. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2020, 16:05 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик Давно тут смотрю ConfigureAwait не обсуждалось ))) А чё тут обсуждать? Если вы делаете библиотеку -- нужен. В прикладном коде -- не нужен. Если контекст синхронизации отсутствует, то в общем-то совершенно пофиг. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2020, 22:04 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
hVostt А чё тут обсуждать? Если вы делаете библиотеку -- нужен. В прикладном коде -- не нужен. Ну вот приведенный код определенно "прикладной", или можно сказать client side. Вьюха для WPF формы, которая работает с UI дергает WCF службу у клиента которой под капотом свои нормальные прикладные методы. То есть можно косвенно считать что вы сказали "не нужен" fkthat вот считает что "нужно". полагаю он имел в виду конкретный пример, жаль чуть подробнее не раскрыл "почему" это нужно. "прикладной" код - тоже довольно размазанное понятие и всегда могут найтись разные НО. а есть те кто считает что "везде" нужно, и это вроде правило хорошего тона и показатель профессионализма. я не совсем понимаю профит от приведенного в примере кода. в моей картине мира ConfigureAwait - это "оптимизация", то есть полезная плюшка а не have to. с серверной стороной понятно, когда мы ставим ConfigureAwait(false), упрощенно, мы не привязываем Task к потоку и в итоге возможно более эффективное использование пула потоков и сервер большую нагрузку переваривает. собственные библиотеки которым не важен контекст тоже понятно - дедлоки, префоманс и т.д.. но код который непосредственно с UI работает, все методы юзают контекст, что мы оптимизировали? то что DoSomeAction может не заканчиваться в UI потоке, и не нужно при завершении ReloadAsync (который выполнялся в UI потоке) эвэйтору цепляться снова к UI потоку а можно взять поток из пула и тут же завершиться? то есть мы оптимизировали одно "переключение". И это значимо при обработке клика по кнопке? тяжелые методы - обращения к WCF, так там и так асинхронные методы которые не будут грузить UI поток. при этом есть кейсы когда ConfigureAwait(false) может быть более актуальным почти в UI коде Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
и то, это наверняка будет быстрее работать, но на современном компе с не сложным application профит можно будет замерить только приборами. а повсеместное использование ConfigureAwait в UI коде (где в отличии от сервера, где 99% ConfigureAwait(false), в UI будут временами чередоваться false/true) это определенное усложнение. если через X месяцев кто-то будет дорабатывать код и не заметив что ConfigureAwait(false); допишет Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
И получит ошибку, а может и не получит, а может на продакшене у одного из 10 пользователей такое будет вылетать раз в неделю. был пример как старый код, который использовал Monitor.Enter/Exit, внутри получил асинхронный метод, и пол года работал прежде чем стали появляться странные ошибки "Enter сделали не в том потоке в котором пытаетесь сделать Exit"... а потом все "о.. ну нельзя же Monitor & Task использовать!". то есть на мой взгляд это в определенной степени усложнение и потенциальные грабли. если это использовать, то имхо оно должно быть оправдано. Или я не прав ошибаюсь в рассуждениях и CA2007 не зря мозолит глаз и правильные пацаны даже в UI обработчиках должны ConfigureAwait ставить со всеми await? если это have to то ткните меня носом в статью майкрософта и какого-нить рихтера где про такой подход написано. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2020, 23:43 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик в моей картине мира ConfigureAwait - это "оптимизация", то есть полезная плюшка а не have to. Это не "оптимизация". В некоторых случаях, без ConfigureAwait вы получите dead lock. Кифирчик то есть на мой взгляд это в определенной степени усложнение и потенциальные грабли. если это использовать, то имхо оно должно быть оправдано. Мне кажется вы слишком много тратите время на пустяки. Ещё раз. Правило. Если это ваш код, вы можете не добавлять ConfigureAwait(false), даже там где он может потребоваться, так как сможете это исправить. Если вы разрабатываете библиотеку, которая будет использоваться в других проектах, то обязаны это делать. По крайне мере, пока ситуация не изменится. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 00:52 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 00:59 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
hVostt Если вы делаете библиотеку -- нужен. В прикладном коде -- не нужен. 1) По моим понятиям, если ты что-то выделяешь в отдельный csproj/сборку, то ты это уже обязан писать, как если бы это была библиотека (проверки параметров, XML-докс, ConfigureAwait, и т.п.) 2) Все средства Code Analysis (FxCop, ReSharper, и даже просто VS) настоятельно подсказывают ConfigureAwait ставить и даже помогают это сделать автоматически по шорткату, т.ч. почему бы просто не следовать их советам. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 06:31 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
hVostt Это уже пруф. Спс. fkthat 1) По моим понятиям, если ты что-то выделяешь в отдельный csproj/сборку, то ты это уже обязан писать, как если бы это была библиотека (проверки параметров, XML-докс, ConfigureAwait, и т.п.) а если в отдельной сборке находится аддон в котором UI форма? fkthat 2) Все средства Code Analysis (FxCop, ReSharper, и даже просто VS) настоятельно подсказывают ConfigureAwait ставить и даже помогают это сделать автоматически по шорткату, т.ч. почему бы просто не следовать их советам. То есть нужно ставить всегда, анализатор советует ставить везде. Получается ваши понятия по отношению ConfigureAwait - по большей части это подмножество общего правила "следовать подсказкам анализатора". Оппонирую: есть некий перечень от Microsoft и все средства ориентируются на него и соответственно "настоятельно рекомендуют". К слову автор статьи (ссылка чуть выше и для которой есть хороший перевод на хабре), который судя по всему сотрудник Microsoft, на эту тему так высказался. авторI agree turning on CA2007 does the wrong thing for app-level code, and basically shouldn’t be turned on for such scenarios. I’m not sure if there’s a good way to augment the rule to tell the two kinds of code apart, though. Please feel free to open an issue in dotnet/roslyn-analyzers. Перевод в двух словах: "я думаю анализатор не должен применять это правило к app-level code... сделайте ишью на эту тему создателям анализатора roslyn." ... хотя не знаю как они должны определить что этот код "app-level" и к нему правило не применять. и наверно не с проста придуманы штуки вроде такой то есть авторы списка предупреждений понимали что не смотря на то что в нем сосредоточены Best practice могут быть ситуации когда им не обязательно следовать и сделали возможность выключения конкретных Warnings. А тот же Resharper позволяет это правило отключить в два клика. и не с проста эти штуки назвали Warnings. Если в 99% случаев нужно ставить .ConfigureAwait(false) то почему сразу поведение не сделано так чтоб false был умолчанию? Если обязательно нужно следовать правилу что await не может быть без .ConfigureAwait то почему это не сделано Error вместо Warning? Как я понимаю, согласия в сообществе на эту тему нет, для кого-то warnings - закон, кто-то забивает, а кто-то выключает. И, понятия "прикладной код"/"app-level code" очень относительно и позволяет себя широко трактовать. А попугаи будут у всех свои, основанные на личном опыте и субъективных убеждениях. Подходящие кейсы и обоснования для себя найдут сторонники любого подхода. Про тот же "ConfigureAwait то почему это не сделано Error вместо Warning" с одной стороны можно сказать "чтоб программист думал и сам принимал решение нужна ли здесь следовать рекомендации", с другой стороны - "чтоб завелись тонны говнокода написанные за последние 20 лет на шарпе". ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 10:56 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
fkthat 1) По моим понятиям, если ты что-то выделяешь в отдельный csproj/сборку, то ты это уже обязан писать, как если бы это была библиотека (проверки параметров, XML-докс, ConfigureAwait, и т.п.) XML документация -- да, однозначно, без вопросов. ConfigureAwait -- вовсе не обязательно, а в случае, если у тебя нет контекста синхронизации, абсолютно бессмысленное действие, не нужно тратить на это время, это глупо :) fkthat 2) Все средства Code Analysis (FxCop, ReSharper, и даже просто VS) настоятельно подсказывают ConfigureAwait ставить и даже помогают это сделать автоматически по шорткату, т.ч. почему бы просто не следовать их советам. Ничего не надо делать бездумно. Нужно чётко понимать для чего ты это делаешь. Про публичные библиотеки такое правило действует по следующим причинам: 1. Пользователь твоей библиотеки не может сам исправить проблему, так как у него на руках готовая сборка. 2. Пользователь твоей библиотеки может использовать её в среде, где есть контекст синхронизации. 3. Пользователь твоей библиотеки может заблокировать вызов в синхронном стиле, что может привести к дедлоку. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 13:26 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик То есть нужно ставить всегда, анализатор советует ставить везде. Получается ваши понятия по отношению ConfigureAwait - по большей части это подмножество общего правила "следовать подсказкам анализатора". Нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 13:27 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик Если в 99% случаев нужно ставить .ConfigureAwait(false) то почему сразу поведение не сделано так чтоб false был умолчанию? Потому что основная масса разработчиков -- прикладные программисты, а не разработчики библиотек. Для прикладного кода (часто, даже если это отдельная сборка), CA не нужен. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 13:29 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Вот здесь пример от MS MVP в котором детализировано понятие "прикладной код"/"код библиотеки" вне того как это размещается по сборкам. https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html (раздел Preventing the Deadlock) как я это понял, в двух словах - "прикладной код" - обработчики UI и методы которые непосредственно с UI работают "код библиотеки" - собственные обертки над методами получения данных (веб/wcf/sql), работы с файловой системой, свои емкие вычисления и в этих методах нет работы с UI ConfigureAwait(false) - в библиотеках. ConfigureAwait(true) либо без него - в прикладном коде. вот еще, там пример косвенно подтверждает мою мысль https://blog.stephencleary.com/2012/02/async-and-await.html раздел Avoiding Context и ниже в комментах фраза автора This pattern is rather common: library async methods do use ConfigureAwait, and UI async methods do not use ConfigureAwait ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 19:57 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик, Ну вы на примеры-то посмотрите сначала, я выделил цветом на что обратить внимание: deadlock 1: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
В прикладном коде поток блокируется, поэтому GetJsonAsync не может вернуться в уже заблокированный поток контекста синхронизации. deadlock 2: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
Аналогично. Проблема по сути не отсутствии ConfigureAwait(false), а в некорректной работе с асинхронным методом. Если вы собираетесь в патроны насыпать пыльцу вместо пороха, чтобы дядятко не отстрелило себе серое вещество — это не решение проблемы. Собственно поэтому и говорится, что это нужно делать в библиотеках, так как прикладные программисты часто не очень умные :) ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 22:30 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
hVostt, не понял на счет пыльцы вместо пороха )))) моя проблем - коллеги которые фанатично придерживаются взглядов fkthat ))) а когда сильно "веришь" то нужно что-то очень тяжелое чтоб чуток пододвинуть картину мира. ради объективности - ко мне это кстати тоже относится. мне интересны мнения других разработчиков и пруфы в поддержку той или иной точки зрения. собственно в примерах я отмечаю как разработчик показывает "правильные" подходы. и уже есть несколько (пруфов) мнений разработчиков Microsoft где упоминается что в top-level/app-code/client side code не тарахтел ConfigureAwait. Есть мнение что анализатор в UI коде не должен парить с предупреждением о ConfigureAwait. По примерам можно понять что они подразумевают под "top-level/app-code/client side code" & library code и пока что рекомендованная практика (в части разделения на слои) выглядит как в примере ниже Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
И примеров где прямо в обработчике есть ConfigureAwait мне не попалось. Только вариации в слое "библиотечных" методов. я допускаю что могу заблуждаться, но пока то что было накопано в поддержку точки зрения "не нужно в top-level ConfigureAwait(false)" заметно весомее чем "анализатор плохого не посоветует". ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2020, 23:31 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик Есть мнение что анализатор в UI коде не должен парить с предупреждением о ConfigureAwait. Я считаю, и продолжаю об этом говорить, что не нужно заниматься трудом, который может сделать за вас компьютер. Представляете как это выглядит, а? Некий анализатор говорит, что вам нужно дописать некий обязательный код. А что ж он (мудила) сам не добавит его тогда? :)) https://github.com/Fody/ConfigureAwait ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 00:10 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик заметно весомее чем "анализатор плохого не посоветует". Я всё ж вам предложу два выхода из ситуации: 1) если верите, хотя бы автоматизируйте свой труд, не пишите руками 2) перестать верить и начать думать :) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 00:12 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Возможно нужно придерживаться подхода, что команда может выполняться в асинхронном режиме или в другом потоке, но все операции, затрагивающие UI должны выполняться в контексте UI(через Dispatcher.Invoke)? То есть разные команды выполняем без разницы как, но если нужно что-то сделать с UI, то делаем это через Dispatcher.Invoke? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 08:51 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
hVostt, Result и Wait выжигать раскаленным железом. Я бы был вообще за то чтобы эту стрелялку в ногу из API убрать :)) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 10:40 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик заметно весомее чем "анализатор плохого не посоветует". Если у меня нет времени/ресурсов проверить чей-то совет, то для меня умолчательное поведение этому совету последовать. 90+ процентов, что советующий не от балды это выдумал. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 10:47 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
vb_sub Возможно нужно придерживаться подхода, что команда может выполняться в асинхронном режиме или в другом потоке, но все операции, затрагивающие UI должны выполняться в контексте UI(через Dispatcher.Invoke)? То есть разные команды выполняем без разницы как, но если нужно что-то сделать с UI, то делаем это через Dispatcher.Invoke? Не нужно, при использовании async/await с контекстом синхронизации, всё делается за вас. Если конечно всё делать правильно :) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 16:40 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
fkthat Result и Wait выжигать раскаленным железом. Я бы был вообще за то чтобы эту стрелялку в ногу из API убрать :)) Просто Task появился задолго до TAP. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 16:41 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
в голове продолжает вариться ))) ... еще немного покопал... интересная картина получается если открыть описание рекомендации анализатора CA2007: Do not directly await a Task, то там такое Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
То есть эта рекомендация актуальна тех ситуаций в которых есть контекст синхронизации (о чем много раз намекал hVostt), и из примеров контексто зависимой задачи - UI поток. Также видос на канале MSDN/ подпись под видео Код: plaintext 1. 2.
По описанию CA2007 и пары видосов на подобии последнего прослеживается акцент на UI, можно сделать вывод что задумка ConfigureAwait(false): 1) защита от дедлоков - так как люди часто натягивают async на синхронный код и пишут всякие Result/Wait - ConfigureAwait(false) в UI библиотеках позволяет минимизировать вероятность дедлоков при неправильном использование этих библиотек. 2) micro-optimization для библиотек работающих с UI, так как возврат в поток UI (или любой другой контекст) "дорогая" операция, и ConfigureAwait(false) позволяет этим управлять и делать UI в частности более отзывчивым. Относительно серверов - по буржуйским форумам попадалось мнение, что ConfigureAwait(false) будет полезен на серверах с большой нагрузкой, у которых очень много коннектов и не CPU операций, а операций ввода/вывода, для которых есть честные async методы на уровне драйверов. То есть в ситуациях когда таски в большей степени ожидают ввода/вывода с диска или по сети чем что-то майнят на CPU. Из прочитанного ранее - "if you’re writing app-level code, do not use ConfigureAwait(false)" Я перечитал, и то и то и сперва завис. В одном месте - "используйте для оптимизации и защиты от дедлоков в UI", в другом - в "прикладном коде с UI не используйте". но уравнения сходятся если определить грань между "прикладным кодом" и "библиотеками общего назначения". резюме по топику - в первую очередь ConfigureAwait(false) имеет смысл для библиотек с асинхронными методами потребитель которых имеет контекст синхронизации - UI (WinForms/WPF) & ASP.NET для защиты от глупого использования и дедлоков. - во вторую - для микро-оптимизации, чтоб внутри библиотечных методов, к примеру где нет необходимости в доступе к UI - отпускать UI поток - в третью, оптимизация на супер загруженных системах, hi load в остальных случаях он абсолютно не нужен, рекомендация CA2007 может быть смело выключена из warnings, и это не несет последствий перфомансу (как к примеру игнорирование CS1998) и, отвечая на свой вопрос в первом сообщении - полагаю таки обработчики UI таки не относятся к "your library routine might be called from the UI thread". UI обработчики это уже самое крайнее допущение к которому можно пододвинуть границу general-purpose library code. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2020, 23:11 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик, Вот это ещё почитайте: https://blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2020, 00:17 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
hVostt Вот это ещё почитайте: https://blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html Этот товарищ кстати книжку "Конкурентность в C#" написал. По статье, интересное попадается в комментах ))) Код: plaintext 1. 2. 3. 4. 5. 6. 7.
... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2020, 13:37 |
|
Нужен ли в примере ConfigureAwait и если да то какой профит это дает?
|
|||
---|---|---|---|
#18+
Кифирчик Этот товарищ кстати книжку "Конкурентность в C#" написал. Этот товарищ большой молодец, но слепо пользоваться его решениями я бы не стал. Например, его реализация асинхронной блокирующей очереди -- тормозной отстой. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2020, 14:09 |
|
|
start [/forum/topic.php?fid=20&msg=39984065&tid=1398499]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
137ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
59ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 259ms |
0 / 0 |