C# Portal | Программирование
13.2K subscribers
1.43K photos
132 videos
31 files
1.08K links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

Сотрудничество, реклама: @devmangx

Работаем с @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
BenchmarkDotNet в .NET Single-File приложениях

Бенчмарки — отличный сценарий использования одnofайловых приложений (Single-File Apps) в .NET.

В примере показано, как использовать BenchmarkDotNet в таком приложении. Самые важные настройки находятся в начале кода, а также стоит обратить внимание на атрибут [InProcess].

Автор делится примером реализации и готов отправить исходный код тем, кто заинтересуется им в комментариях.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾4
Please open Telegram to view this post
VIEW IN TELEGRAM
😁13👨‍💻3🍾1👀1
CQRS без Event Sourcing: используйте сильные стороны EF Core и Dapper

Чтобы получить преимущества CQRS, не обязательно внедрять полноценный Event Sourcing.

Достаточно разделить модели записи и чтения:

• EF Core — для бизнес-правил, доменных агрегатов и операций записи.
• Dapper — для быстрых SQL-запросов и чтения данных.

Такой подход позволяет сохранить бизнес-логику в одном месте, а запросы к данным сделать проще и производительнее.

Прагматично, чисто и без лишней сложности.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🍾2
Message Brokers гарантируют At-Least-Once, а не Exactly-Once

Что произойдёт, если ваш consumer обработает одно и то же событие дважды? Сможет ли система корректно справиться с повторной доставкой?

Брокеры сообщений часто используют семантику доставки At-Least-Once — событие будет доставлено как минимум один раз, но возможны дубликаты.

Поэтому обработчики событий должны быть идемпотентными (Idempotent): повторная обработка одного и того же события не должна приводить к повторным побочным эффектам.

Разберём, как проектировать идемпотентные обработчики событий и защищать систему от дублирующей обработки.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🍾1
Зачем обрабатывать элементы по одному, если процессор может обрабатывать сразу 8?

В C# есть инструменты для использования SIMD (Single Instruction, Multiple Data) — технологии, которая позволяет выполнять одну операцию одновременно над несколькими элементами данных.

Для этого можно использовать Vector<T> и Hardware Intrinsics.

Что они дают?

Vector<T> — позволяет обрабатывать несколько значений одного типа за одну операцию.

Hardware Intrinsics — дают более низкоуровневый доступ к SIMD-инструкциям процессора, например AVX2 и AVX-512.

SIMD — ускоряет вычисления над массивами чисел, обработку изображений, математические операции и другие задачи с однотипными данными.

И всё это доступно прямо в C# — без необходимости переходить на C++.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔5👍2🔥2🍾1
Учитывают ли ваши C#-структуры кэш-линии процессора?

Неправильное расположение полей структуры приводит к неэффективному использованию памяти и дополнительным затратам на доступ к кэш-линии процессора.

Используйте [StructLayout(LayoutKind.Sequential, Pack = 1)], чтобы контролировать размещение полей в памяти.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🤔2👏1🍾1
Каждый раз, когда асинхронный метод возвращает Task<T>, при завершении операции выделяется память в куче.

Если ваш метод часто завершается синхронно (например, при попадании в кеш), используйте ValueTask<T>.

Это поможет избежать миллионов лишних выделений памяти (heap allocations).


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾4
Запускаете несколько реплик фонового воркера в Kubernetes?

Локальные блокировки (lock / Monitor) не работают между разными контейнерами.

Используйте распределённые блокировки Redis (Redis Distributed Locks) с fencing-токенами, чтобы предотвратить состояния гонки (race conditions) и избежать одновременного выполнения одной задачи несколькими воркерами.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3❤‍🔥2🍾2
Получаете случайные ошибки 502 Bad Gateway во время деплоя в Kubernetes?

Вероятно, ваше .NET-приложение завершает работу до того, как входящий трафик будет перенаправлен на другие экземпляры.

Разберитесь, как правильно настроить graceful shutdown и health probes в ASP.NET Core.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾3
Task.WhenAll vs Parallel.ForEachAsync в .NET: что выбрать?

Оба инструмента позволяют выполнять независимые операции конкурентно, но отличаются способом управления параллельностью и ресурсами.

Правильный выбор зависит от типа нагрузки.

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?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
CQRS ≠ MediatR.

Перестаньте смешивать CQRS и MediatR.

То, что вы используете MediatR, не означает, что у вас реализован CQRS.

CQRS — это про разделение операций чтения и записи, часто с разными моделями, стратегиями хранения и иногда с разными хранилищами данных.

MediatR — это библиотека для диспетчеризации сообщений внутри процесса. Она удобна для организации команд и запросов, но это не фреймворк CQRS.

Можно использовать MediatR в архитектуре, построенной по CQRS.

Но не стоит считать, что одно автоматически означает другое.

Сначала разберитесь в различии, прежде чем внедрять паттерн или инструмент.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7👏1🍾1
Бесплатный декомпилятор .NET

Инструмент позволяет декомпилировать приложения в C#, восстанавливать целые проекты, искать методы и классы, изучать иерархию типов и просматривать метаданные.

Также доступен в виде расширений для Visual Studio и VS Code, а для работы из терминала есть CLI-версия.

https://github.com/icsharpcode/ILSpy

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3