Process API Improvements in .NET 11 – Команда .NET наконец-то завезла нормальный API для запуска процессов. Однострочник Process.RunAndCaptureText() сам читает stdout/stderr через мультиплексирование и не уходит в дедлок на буфере пайпа (тот самый, об который спотыкались примерно все). Подвезли KillOnParentExit для борьбы с осиротевшими процессами, контроль наследования хендлов, StartDetached и трим-френдли SafeProcessHandle. Под капотом: на Windows BeginOutputReadLine больше не блокирует два потока тредпула (+1.8x throughput), на Apple Silicon переход на posix_spawn дал 98x ускорения старта процесса (не опечатка) , на Unix минус 30-50% аллокаций.
.NET MAUI переезжает на CoreCLR в .NET 11 – Начиная с Preview 4, мобильные приложения на MAUI (Android, iOS, Mac Catalyst) теперь работают на CoreCLR том же рантайме, что и ASP.NET Core (прощай, Mono, ты был хорош, спасибо за 15 лет страданий). Обещают tiered JIT, ReadyToRun, PGO и дорогу к NativeAOT на мобилках. Перформанс как повезет на пустом dotnet new maui старт быстрее, на реальных проектах community уже отрепортил регрессии по размеру и старту (сюрприз-сюрприз) . Если что есть <UseMonoRuntime>true</UseMonoRuntime> для отката, но это временно, как водится. Blazor WASM остается на Mono, не паникуем.
.NET 11 Preview 4 уже здесь – Очередной превью с традиционным "улучшения везде, читайте release notes". Из заметного: Process получил самый большой апдейт за годы, Span-based API для Deflate/GZip, рантайм-либы теперь компилируются с runtime-async, dotnet watch доехал до Android и iOS (в 2026, прогресс не остановить), в ASP.NET Core завезли HTTP QUERY в OpenAPI и шаблон MCP Server прямо в SDK (куда же в 2026 без MCP). EF Core порадует approximate vector search для SQL Server 2025, векторные БД пришли и за реляционщиками. До GA в ноябре успеют ещё пару раз все переписать, по классике.
.NET и .NET Framework майские servicing-обновления – Ежемесячный ритуал: четыре свежих CVE (три EoP и один DoS, классика жанра), патчи прилетели в .NET 10/9/8 и во весь зоопарк .NET Framework вплоть до 3.5 (да, оно все еще живо и патчится, не спрашивайте). Качаем 10.0.8, 9.0.16, 8.0.27 и идем дальше работать.
TimescaleDB для EF Core, апдейт с поддержкой .NET 10 – Автор пилит pet-project, который добавляет в Npgsql-провайдер EF Core нормальную поддержку TimescaleDB (потому что писать .Sql("SELECT create_hypertable(...)") руками в миграциях надоедает примерно к третьей таблице). За полгода завезли continuous aggregates с refresh-политиками, data retention policies (чтобы старые чанки уезжали сами, а не по пятничному алерту в три ночи), тонкую настройку компрессии через SegmentBy/OrderBy, EF.Functions.TimeBucket() для LINQ, совместимость с Apache Community Edition и EFCore.NamingConventions, плюс фиксы scaffolding для database-first. В планах переписать кодогенерацию, чтобы scaffolding выдавал нормальный Fluent API вместо простыни .HasAnnotation(...), добавить extension-методы для миграций вместо .Sql()(автор честно мучается классической дилеммой: красиво vs видно что выполнится) и затащить Hypercore. Звезд на гитхабе пока 50, но проект из тех, что закрывают вполне реальную боль .NET-щиков, живущих на временных рядах.
Статьи
Writing Allocation-Free Code in .NET – Большой гайд по тому, как не насиловать GC: stack vs heap, readonly struct/ref struct, Span<T>/Memory<T>, ArrayPool/MemoryPool/ObjectPool, stackalloc(тот самый, который JIT когда-нибудь сделает ненужным благодаря escape analysis, но пока пишем руками), борьба с боксингом и скрытыми аллокациями в строках, LINQ и замыканиях, плюс ValueTask и IValueTaskSource для асинхронщины без мусора. Главный посыл здравый: zero-alloc нужен только в hot path, все остальное преждевременная оптимизация (но мы-то знаем, что найдется мастер, который натащит stackalloc в контроллер регистрации пользователя). В финале обязательный набор инструментов: BenchmarkDotNet с MemoryDiagnoser, dotMemory, PerfView и тесты с GC.GetAllocatedBytesForCurrentThread() для защиты от регрессий в CI.
Подводные камни gRPC – Автор перетащил сотню моделей с REST и WCF на gRPC и записал все грабли, на которые наступил (чтобы вы наступили только на половину). В меню: decimal в protobuf не существует (используем DecimalValue от Microsoft, но без implicit operator иначе словите NRE на ровном месте), optional int дает не int?, а свойство с флагом HasValue(сюрприз для всех, кто пришел из C#), DateTime требует ToUniversalTime() перед ToTimestamp()(а DateTimeOffset нет, логика на уровне). Наследования нет есть композиция в двух вкусах (от детей к родителям или наоборот, оба больно), дженериков нет есть три способа боли: специализированные сообщения, oneof или Any(type safety vs гибкость, выбери одно). Enum-значения должны быть уникальны в пределах файла (C++ scoping rules, привет из 70-х) и первое обязано быть 0 добавляйте Undefined = 0 и не смещайте legacy. Для object четыре всадника: Any, oneof, Value/Struct, ручная сериализация в string(автор честно признался, что у них на бэке object "приходило и уходило", поэтому забили и взяли string святая правда жизни). Обновлено под protoc v34.1 и .NET 10, сохраняйте в закладки, пригодится.
Архитектура MassTransit как устроена библиотека под капотом – Автор написал лонгрид о том, что творится в кишках самой популярной .NET-обвязки над брокерами (спойлер: это не просто обертка над RabbitMQ). Все построено на pipeline в духе middleware, который раньше жил отдельной библиотекой GreenPipes но ее скопипастили внутрь, потому что больше никто ей не пользовался. Под капотом классический зоопарк: Agents/Supervisors, Filters/Pipes, Observers, Configurators, все в дженериках по самые уши. Отдельно разобрано, зачем нужен ChannelExecutor(потому что IModel нельзя дергать из нескольких потоков, иначе AMQP framing рассыпется) и почему появляется загадочная очередь Desktop..._bus_.... Большой кусок про SagaStateMachine это FSM с состояниями и переходами (автор честно проводит параллель с тем, как компилятор разворачивает async/await там та же математика). Ключевая мысль: состояние саги живет в БД и если сервис упал посреди behavior MassTransit не восстанавливает шаги, а начинает заново с последнего закоммиченного CurrentState(идемпотентность ваша забота, как обычно). Полезно для тех, кто устал гадать почему оно работает и хочет понять, почему именно так.
Генерация типов в Runtime – Автор закопался в System.Reflection.Emit и показал как создавать классы налету (на случай если вы пишете маппер, динамическое прокси или просто любите боль). Начали с классики, простыня из ILGenerator.Emit(OpCodes.Ldarg_0) и прочих радостей IL, потом обернули это в декларативную фабрику с fluent API (стало читаемо, но писать тело методов в IL все равно не доставляет). Тогда автору пришла светлая мысль, а пусть тело методов генерируется через Expression Trees, которые сами компилируются в IL и все бы хорошо, но LambdaCompiler внутри System.Linq.Expressions помечен как internal (а как же иначе). Поэтому в ход пошла "черная магия и грязное свинство", рефлексия по приватным полям _ilg, _hasClosureArgument и _method, чтобы подсунуть свой ILGenerator и убедить компилятор, что замыкания нет. Работает! (до следующего обновления .NET, но это уже детали). В финале обещание разобрать Roslyn как более цивилизованную альтернативу для тех, кто не готов жить на приватной рефлексии в проде.
Async/Await в C# это синтаксический сахар для конечного автомата – Перевод (очередной статьи по теме) о том, как компилятор разворачивает async/await в IAsyncStateMachine. На примере простого await client.GetStringAsync(...) разбирается как метод превращается в класс с состояниями (-1 начальное, 0,1,2... по числу await'ов, -2 финальное), как вся логика переезжает в MoveNext() и что делает AsyncTaskMethodBuilder под капотом (захватывает ExecutionContext, регистрирует продолжение через AwaitUnsafeOnCompleted, возвращает Task вызывающему все то, что вы уже читали раз пятнадцать, но в шестнадцатый раз вдруг щелкнет). В финале есть цветная схема FirstCall vs WakeUpCall для тех, кто лучше воспринимает картинки. Полезно дать джуну на собеседовании, чтобы перестал отвечать "ну, await это типа поток ждет".
Голос в текст, текст в перевод: строим десктопное приложение для распознавания речи с Azure Speech SDK и NAudio – Туториал о сборке AzioSpeech на .NET 9 + Avalonia. Распознавание речи в реальном времени, диаризация спикеров и перевод на 9 языков через Azure Speech SDK. Avalonia взяли ради ReactiveUI от Fody (чтобы не писать INotifyPropertyChanged руками), но приложение все равно Windows-only NAudio под капотом дергает WinMM API. Архитектура простая: AudioCaptureService ловит PCM с микрофона и кидает события на которые подписываются сервисы транскрипции и перевода, пишущие байты в PushAudioInputStream. Из граблей: строго 16 kHz / 16-bit / моно (иначе SDK не примет), копирование буфера вместо ссылки (NAudio его переиспользует классика), ConfigureAwait(false) везде против дедлоков в Avalonia. Диаризация через ConversationTranscriber(не путать с двумя свежими deprecated сервисами Microsoft устроила знатный зоопарк названий). Ключ Azure шифруется через DPAPI, а не лежит в plaintext (потому что это пароль к биллингу). В бонусе гайд по получению ключей и напоминание, что Free tier дает 5 часов в месяц.