Task.WhenAll vs Parallel.ForEachAsync в .NET: что выбрать?
Оба инструмента позволяют выполнять независимые операции конкурентно, но отличаются способом управления параллельностью и ресурсами.
Правильный выбор зависит от типа нагрузки.
1. Task.WhenAll. Лучше всего подходит для известного набора независимых асинхронных операций, особенно связанных с вводом-выводом (I/O-bound).
• Идеален для нескольких независимых запросов к API или базе данных.
• Не имеет встроенного ограничения количества одновременно выполняемых операций.
• Не создаёт потоки автоматически.
2. Parallel.ForEachAsync. Лучше всего подходит для обработки коллекций с контролируемым уровнем параллельности.
• Поддерживает I/O-bound и CPU-bound нагрузки.
• Имеет встроенный механизм ограничения параллельности.
• Полезен при обработке больших коллекций и выполнении внешних API-запросов.
3. Что выбрать?
• CPU-bound: предпочитайте
• I/O-bound: используйте
Внешние API: подходят оба варианта, но
Важное напоминание об EF Core:
Никогда не выполняйте параллельные запросы через один и тот же экземпляр
Главное:
•
•
И помните: по умолчанию
Какой из этих инструментов вы чаще используете в production-приложениях на .NET?
👉 @KodBlog
Оба инструмента позволяют выполнять независимые операции конкурентно, но отличаются способом управления параллельностью и ресурсами.
Правильный выбор зависит от типа нагрузки.
1. Task.WhenAll. Лучше всего подходит для известного набора независимых асинхронных операций, особенно связанных с вводом-выводом (I/O-bound).
var usersTask = GetUsersAsync();
var ordersTask = GetOrdersAsync();
await Task.WhenAll(usersTask, ordersTask);
• Идеален для нескольких независимых запросов к API или базе данных.
• Не имеет встроенного ограничения количества одновременно выполняемых операций.
• Не создаёт потоки автоматически.
2. Parallel.ForEachAsync. Лучше всего подходит для обработки коллекций с контролируемым уровнем параллельности.
await Parallel.ForEachAsync(
orders,
new ParallelOptions
{
MaxDegreeOfParallelism = 10
},
async (order, ct) =>
await ProcessOrderAsync(order, ct));
• Поддерживает I/O-bound и CPU-bound нагрузки.
• Имеет встроенный механизм ограничения параллельности.
• Полезен при обработке больших коллекций и выполнении внешних API-запросов.
3. Что выбрать?
• CPU-bound: предпочитайте
Parallel.ForEach для синхронных операций с высокой вычислительной нагрузкой.• I/O-bound: используйте
Task.WhenAll для нескольких независимых операций или Parallel.ForEachAsync, если необходимо ограничить параллельность.Внешние API: подходят оба варианта, но
Parallel.ForEachAsync часто удобнее для обработки сотен запросов без чрезмерной нагрузки на внешние сервисы.Важное напоминание об EF Core:
DbContext не является потокобезопасным (thread-safe).Никогда не выполняйте параллельные запросы через один и тот же экземпляр
DbContext. Используйте отдельные экземпляры или выполняйте запросы последовательно.Главное:
•
Task.WhenAll ожидает завершения нескольких задач без встроенного ограничения параллельности.•
Parallel.ForEachAsync обрабатывает коллекции с ограниченным уровнем параллельности.И помните: по умолчанию
Parallel.ForEachAsync допускает количество одновременно выполняемых операций, равное Environment.ProcessorCount. Настраивайте MaxDegreeOfParallelism с учётом особенностей вашей нагрузки.Какой из этих инструментов вы чаще используете в production-приложениях на .NET?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🍾1
CQRS ≠ MediatR.
Перестаньте смешивать CQRS и MediatR.
То, что вы используете MediatR, не означает, что у вас реализован CQRS.
CQRS — это про разделение операций чтения и записи, часто с разными моделями, стратегиями хранения и иногда с разными хранилищами данных.
MediatR — это библиотека для диспетчеризации сообщений внутри процесса. Она удобна для организации команд и запросов, но это не фреймворк CQRS.
Можно использовать MediatR в архитектуре, построенной по CQRS.
Но не стоит считать, что одно автоматически означает другое.
Сначала разберитесь в различии, прежде чем внедрять паттерн или инструмент.
👉 @KodBlog
Перестаньте смешивать CQRS и MediatR.
То, что вы используете MediatR, не означает, что у вас реализован CQRS.
CQRS — это про разделение операций чтения и записи, часто с разными моделями, стратегиями хранения и иногда с разными хранилищами данных.
MediatR — это библиотека для диспетчеризации сообщений внутри процесса. Она удобна для организации команд и запросов, но это не фреймворк CQRS.
Можно использовать MediatR в архитектуре, построенной по CQRS.
Но не стоит считать, что одно автоматически означает другое.
Сначала разберитесь в различии, прежде чем внедрять паттерн или инструмент.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👏1🍾1
Бесплатный декомпилятор .NET
Инструмент позволяет декомпилировать приложения в C#, восстанавливать целые проекты, искать методы и классы, изучать иерархию типов и просматривать метаданные.
Также доступен в виде расширений для Visual Studio и VS Code, а для работы из терминала есть CLI-версия.
https://github.com/icsharpcode/ILSpy
👉 @KodBlog
Инструмент позволяет декомпилировать приложения в C#, восстанавливать целые проекты, искать методы и классы, изучать иерархию типов и просматривать метаданные.
Также доступен в виде расширений для Visual Studio и VS Code, а для работы из терминала есть CLI-версия.
https://github.com/icsharpcode/ILSpy
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🐳2🍾1
Отличная шпаргалка для C#-разработчиков, которые регулярно работают с Git.
Создание коммитов, переключение между ветками, разрешение конфликтов, отмена изменений, работа с удалёнными репозиториями и история проекта.
80 команд с короткими пояснениями и примерами.
👉 @KodBlog
Создание коммитов, переключение между ветками, разрешение конфликтов, отмена изменений, работа с удалёнными репозиториями и история проекта.
80 команд с короткими пояснениями и примерами.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🍾2
Строка, которая рассчитывает скидку, спрятана за четырьмя вложенными
Каждая проверка добавляет новый уровень вложенности, а каждый
Можно начать с обработки случаев, при которых скидка не предоставляется.
Если заказ или клиент отсутствует — метод завершается. То же самое происходит, если клиент неактивен или сумма заказа слишком мала для получения скидки.
После прохождения всех проверок последняя строка может сразу выполнить основную логику.
Правила остаются прежними, но вложенность становится меньше.
Это не означает, что в коде стало меньше ветвлений, а низкая цикломатическая сложность сама по себе ещё не делает код понятным.
Я проверяю, насколько легко проследить каждый путь выполнения, не возвращаясь постоянно к предыдущим строкам.
При рефакторинге обязательно сохраняйте тесты для граничных случаев.
👉 @KodBlog
if.Каждая проверка добавляет новый уровень вложенности, а каждый
else возвращает ноль. Чтобы понять, когда применяется скидка, приходится держать в голове все четыре условия.Можно начать с обработки случаев, при которых скидка не предоставляется.
Если заказ или клиент отсутствует — метод завершается. То же самое происходит, если клиент неактивен или сумма заказа слишком мала для получения скидки.
После прохождения всех проверок последняя строка может сразу выполнить основную логику.
Правила остаются прежними, но вложенность становится меньше.
Это не означает, что в коде стало меньше ветвлений, а низкая цикломатическая сложность сама по себе ещё не делает код понятным.
Я проверяю, насколько легко проследить каждый путь выполнения, не возвращаясь постоянно к предыдущим строкам.
При рефакторинге обязательно сохраняйте тесты для граничных случаев.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🍾1
Вышел Arch Guard v0.4.0 — инструмент для проверки архитектуры .NET-проектов. Помогает разработчикам и ИИ-агентам следить за структурой кода и не допускать архитектурных нарушений.
Попробовать: https://kbourzayq.github.io/arch-guard/
👉 @KodBlog
Попробовать: https://kbourzayq.github.io/arch-guard/
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🍾2
8 ПАТТЕРНОВ КЕШИРОВАНИЯ, которые должен знать C#-разработчик
Кеширование помогает ускорить приложение, снизить нагрузку на базу данных и эффективнее использовать ресурсы. Но важно не просто добавить Redis или
Разбираем основные подходы:
Cache-Aside (Lazy Loading) — приложение сначала проверяет кеш. Если данных нет, загружает их из БД и сохраняет в кеше. Самый распространённый вариант.
Read-Through — приложение запрашивает данные у кеша, а тот самостоятельно загружает их из БД при промахе.
Write-Through — данные одновременно записываются в кеш и БД. Помогает поддерживать согласованность, но увеличивает задержку записи.
Write-Behind (Write-Back) — приложение сначала записывает данные в кеш, а в БД они попадают асинхронно. Выше производительность, но есть риск потери данных.
Write-Around — запись идёт напрямую в БД, минуя кеш. Подходит для данных, которые редко читают.
Refresh-Ahead — кеш заранее обновляет часто используемые данные, не дожидаясь их истечения. Помогает избежать промахов кеша.
TTL + Eviction — TTL задаёт срок жизни записи, а политики вытеснения вроде LRU и LFU определяют, какие данные удалить при нехватке памяти.
Distributed Cache — общий кеш для нескольких экземпляров приложения. В .NET для этого можно использовать
В экосистеме .NET также есть HybridCache — механизм, объединяющий кеш в памяти и распределённый кеш. Он поддерживает защиту от одновременной загрузки одних и тех же данных несколькими запросами.
Главное — выбирать стратегию под сценарий: частоту чтения и записи, требования к согласованности и допустимость потери данных.
👉 @KodBlog
Кеширование помогает ускорить приложение, снизить нагрузку на базу данных и эффективнее использовать ресурсы. Но важно не просто добавить Redis или
MemoryCache, а выбрать подходящую стратегию.Разбираем основные подходы:
Cache-Aside (Lazy Loading) — приложение сначала проверяет кеш. Если данных нет, загружает их из БД и сохраняет в кеше. Самый распространённый вариант.
Read-Through — приложение запрашивает данные у кеша, а тот самостоятельно загружает их из БД при промахе.
Write-Through — данные одновременно записываются в кеш и БД. Помогает поддерживать согласованность, но увеличивает задержку записи.
Write-Behind (Write-Back) — приложение сначала записывает данные в кеш, а в БД они попадают асинхронно. Выше производительность, но есть риск потери данных.
Write-Around — запись идёт напрямую в БД, минуя кеш. Подходит для данных, которые редко читают.
Refresh-Ahead — кеш заранее обновляет часто используемые данные, не дожидаясь их истечения. Помогает избежать промахов кеша.
TTL + Eviction — TTL задаёт срок жизни записи, а политики вытеснения вроде LRU и LFU определяют, какие данные удалить при нехватке памяти.
Distributed Cache — общий кеш для нескольких экземпляров приложения. В .NET для этого можно использовать
IDistributedCache и Redis.В экосистеме .NET также есть HybridCache — механизм, объединяющий кеш в памяти и распределённый кеш. Он поддерживает защиту от одновременной загрузки одних и тех же данных несколькими запросами.
Главное — выбирать стратегию под сценарий: частоту чтения и записи, требования к согласованности и допустимость потери данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍1🍾1
12 МЕТОДОВ LINQ, КОТОРЫЕ ДОЛЖЕН ЗНАТЬ КАЖДЫЙ C#-РАЗРАБОТЧИК
LINQ делает код на C# чище, короче и проще в поддержке.
Вот 12 методов, которые стоит освоить:
• Where() — фильтрует элементы по условию.
• Select() — преобразует элементы в новую форму.
• SelectMany() — объединяет вложенные коллекции в одну.
• Any() — проверяет, есть ли хотя бы один подходящий элемент.
• All() — проверяет, соответствуют ли условию все элементы.
• DistinctBy() — удаляет дубликаты по заданному ключу.
• GroupBy() — группирует элементы по общему ключу.
• OrderBy() — сортирует элементы по возрастанию.
• FirstOrDefault() — возвращает первый подходящий элемент или значение по умолчанию.
• MaxBy() — находит элемент с максимальным значением ключа.
• Chunk() — разбивает коллекцию на пакеты.
• Aggregate() — объединяет элементы в один результат.
Многие LINQ-запросы используют отложенное выполнение (Deferred Execution). Особенно важно понимать, когда именно выполняется запрос при работе с EF Core.
👉 @KodBlog
LINQ делает код на C# чище, короче и проще в поддержке.
Вот 12 методов, которые стоит освоить:
• Where() — фильтрует элементы по условию.
• Select() — преобразует элементы в новую форму.
• SelectMany() — объединяет вложенные коллекции в одну.
• Any() — проверяет, есть ли хотя бы один подходящий элемент.
• All() — проверяет, соответствуют ли условию все элементы.
• DistinctBy() — удаляет дубликаты по заданному ключу.
• GroupBy() — группирует элементы по общему ключу.
• OrderBy() — сортирует элементы по возрастанию.
• FirstOrDefault() — возвращает первый подходящий элемент или значение по умолчанию.
• MaxBy() — находит элемент с максимальным значением ключа.
• Chunk() — разбивает коллекцию на пакеты.
• Aggregate() — объединяет элементы в один результат.
Многие LINQ-запросы используют отложенное выполнение (Deferred Execution). Особенно важно понимать, когда именно выполняется запрос при работе с EF Core.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🍾1
ВЫШЛИ .NET 11 И C# 15! Этот релиз приносит масштабные улучшения во всю экосистему .NET.
От Union Types и Runtime Async до новых API, повышения производительности и мощных возможностей EF Core.
Вот ключевые обновления, которые должен знать каждый .NET-разработчик
1. C# 15
• Union Types — моделирование нескольких возможных типов с проверкой полноты обработки через
• Closed Hierarchies — ограничение наследования пределами сборки, в которой объявлен тип.
• Collection Expressions — поддержка передачи аргументов конструкторам с помощью
• Extension Indexers — добавление индексаторов к существующим типам.
• Labeled Break/Continue — управление выходом из внешних циклов и переходами между ними.
• Memory Safety (Preview) — улучшенная безопасность при работе с неуправляемой памятью.
2. .NET 11 Runtime
• Runtime Async (Preview) — снижение накладных расходов на асинхронность и более понятные трассировки стека.
• JIT Optimizations — улучшенная девиртуализация и устранение проверок границ массивов.
• Native AOT — более быстрый вызов методов через интерфейсы.
• Diagnostics — формирование отчётов о сбоях непосредственно внутри процесса.
3. Библиотеки .NET 11
• LINQ — новые методы
• JSON — поддержка JSON Lines и сериализации Union Types.
• Compression — поддержка алгоритма сжатия Zstandard.
• Numeric Types — новые числовые типы Decimal32, Decimal64 и Decimal128.
• Validation — новые асинхронные API для валидации.
4. .NET 11 SDK и инструменты
• File-Based Apps — поддержка нескольких файлов с помощью
• dotnet test — улучшенное выполнение тестов и формирование отчётов.
• dotnet watch — автоматическое восстановление после сбоев.
• Native AOT CLI — более быстрый запуск CLI-приложений.
5. ASP.NET Core 11
• Async Validation — асинхронные валидаторы в Minimal APIs.
• Localization — встроенная локализация сообщений валидации.
• OpenAPI 3.2 — поддержка по умолчанию, включая схемы SSE.
• MCP — новый шаблон проекта MCP-сервера.
• HTTP/3 — снижение задержки при выполнении первых запросов.
6. EF Core 11
• Query Performance — более эффективная генерация SQL-запросов.
• FullJoin — преобразование запросов в SQL
• MaxBy/MinBy — поддержка трансляции в SQL.
• Vector Search (Experimental) — векторные индексы и поиск по сходству.
• Hybrid Search — объединение векторного и полнотекстового поиска.
• Vector Loading — возможность не загружать векторные столбцы по умолчанию.
Моё мнение:
Union Types — важное дополнение к C#, особенно для моделирования состояний приложения и результатов операций.
Runtime Async выглядит перспективно для высоконагруженных приложений, хотя пока остаётся экспериментальной возможностью.
А возможности векторного поиска в EF Core особенно интересны для создания AI-приложений на SQL Server.
Если вы уже используете .NET 10 LTS, срочной необходимости обновлять production-системы нет.
Но .NET 11 определённо стоит изучить!
Какая функция .NET 11 вас заинтересовала больше всего?
👉 @KodBlog
От Union Types и Runtime Async до новых API, повышения производительности и мощных возможностей EF Core.
Вот ключевые обновления, которые должен знать каждый .NET-разработчик
1. C# 15
• Union Types — моделирование нескольких возможных типов с проверкой полноты обработки через
switch.• Closed Hierarchies — ограничение наследования пределами сборки, в которой объявлен тип.
• Collection Expressions — поддержка передачи аргументов конструкторам с помощью
with(...).• Extension Indexers — добавление индексаторов к существующим типам.
• Labeled Break/Continue — управление выходом из внешних циклов и переходами между ними.
• Memory Safety (Preview) — улучшенная безопасность при работе с неуправляемой памятью.
2. .NET 11 Runtime
• Runtime Async (Preview) — снижение накладных расходов на асинхронность и более понятные трассировки стека.
• JIT Optimizations — улучшенная девиртуализация и устранение проверок границ массивов.
• Native AOT — более быстрый вызов методов через интерфейсы.
• Diagnostics — формирование отчётов о сбоях непосредственно внутри процесса.
3. Библиотеки .NET 11
• LINQ — новые методы
FullJoin и перегрузки Join, возвращающие кортежи.• JSON — поддержка JSON Lines и сериализации Union Types.
• Compression — поддержка алгоритма сжатия Zstandard.
• Numeric Types — новые числовые типы Decimal32, Decimal64 и Decimal128.
• Validation — новые асинхронные API для валидации.
4. .NET 11 SDK и инструменты
• File-Based Apps — поддержка нескольких файлов с помощью
#:include.• dotnet test — улучшенное выполнение тестов и формирование отчётов.
• dotnet watch — автоматическое восстановление после сбоев.
• Native AOT CLI — более быстрый запуск CLI-приложений.
5. ASP.NET Core 11
• Async Validation — асинхронные валидаторы в Minimal APIs.
• Localization — встроенная локализация сообщений валидации.
• OpenAPI 3.2 — поддержка по умолчанию, включая схемы SSE.
• MCP — новый шаблон проекта MCP-сервера.
• HTTP/3 — снижение задержки при выполнении первых запросов.
6. EF Core 11
• Query Performance — более эффективная генерация SQL-запросов.
• FullJoin — преобразование запросов в SQL
FULL JOIN.• MaxBy/MinBy — поддержка трансляции в SQL.
• Vector Search (Experimental) — векторные индексы и поиск по сходству.
• Hybrid Search — объединение векторного и полнотекстового поиска.
• Vector Loading — возможность не загружать векторные столбцы по умолчанию.
Моё мнение:
Union Types — важное дополнение к C#, особенно для моделирования состояний приложения и результатов операций.
Runtime Async выглядит перспективно для высоконагруженных приложений, хотя пока остаётся экспериментальной возможностью.
А возможности векторного поиска в EF Core особенно интересны для создания AI-приложений на SQL Server.
Если вы уже используете .NET 10 LTS, срочной необходимости обновлять production-системы нет.
Но .NET 11 определённо стоит изучить!
Какая функция .NET 11 вас заинтересовала больше всего?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤3🍾1
Union Types появятся в C# 15. Я ждал эту возможность много лет.
Я уже немало писал о паттерне Result. Возьмём простой метод
С Union Types я смогу задать возвращаемый тип
Но больше всего меня радует то, что будет дальше. Допустим, мы добавим третий вариант. Компилятор укажет на все выражения
Как начать работать с Union Types
👉 @KodBlog
Я уже немало писал о паттерне Result. Возьмём простой метод
GetUser(42). Его возвращаемый тип — User. Чтобы узнать, что метод выбрасывает исключение, если пользователь с ID 42 не найден, приходится открывать его реализацию. Слишком много скрытой логики для обычного поиска.С Union Types я смогу задать возвращаемый тип
UserResult с двумя вариантами: User или NotFound. На уровне endpoint можно обработать результат через switch: для User вернуть HTTP 200, а для NotFound(42) — HTTP 404. При этом ID ненайденного пользователя никуда не теряется.Но больше всего меня радует то, что будет дальше. Допустим, мы добавим третий вариант. Компилятор укажет на все выражения
switch, которые по-прежнему обрабатывают только два случая. Можно сразу исправить их, пока изменения ещё свежи в памяти.Как начать работать с Union Types
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7
This media is not supported in your browser
VIEW IN TELEGRAM
Как насчёт партии в Backend? 😴
Дело в чём: 17 ноября AvitoTech проводит Backend Roulette. Инженерные задачи там разложат как покерную партию: за каждым столом эксперт-крупье AvitoTech даст команде вводные, а по ходу игры добавит новые обстоятельства, чтобы перестроить решение.
Можно не садиться за стол и провести время на сайд-активностях или в разговорах с коллегами. После игры всех гостей ждёт афтерпати и нетворк.
И главное: покерный опыт совсем не нужен, достаточно круто провести вечер и понетворкать!
✅ Зарегистрироваться
Дело в чём: 17 ноября AvitoTech проводит Backend Roulette. Инженерные задачи там разложат как покерную партию: за каждым столом эксперт-крупье AvitoTech даст команде вводные, а по ходу игры добавит новые обстоятельства, чтобы перестроить решение.
Можно не садиться за стол и провести время на сайд-активностях или в разговорах с коллегами. После игры всех гостей ждёт афтерпати и нетворк.
И главное: покерный опыт совсем не нужен, достаточно круто провести вечер и понетворкать!
Please open Telegram to view this post
VIEW IN TELEGRAM
👀1