· · 2 минут чтения

.NET 11 наконец исправляет API процессов

System.Diagnostics.Process получает самое большое обновление за годы. RunAndCaptureTextAsync, KillOnParentExit, API SafeProcessHandle и полный контроль над перенаправлением стандартных дескрипторов — больше никакого шаблонного кода для deadlock.

.NET .NET 11 Performance Process API
Эта статья также доступна на:English, Català, Español, Deutsch, Français, Português, Italiano, 日本語, 中文, 한국어, हिन्दी, Polski, Türkçe, العربية, Bahasa Indonesia, Nederlands

Каждый .NET-разработчик, которому когда-либо нужно было запустить процесс и захватить его вывод, написал какую-то вариацию одного и того же опасного шаблонного кода: асинхронное чтение из stdout, асинхронное чтение из stderr, WaitForExitAsync, не забыть очистить оба потока, иначе будет deadlock. Это хорошо известная ловушка, которая существует уже много лет.

.NET 11 наконец-то исправляет это правильно.

RunAndCaptureTextAsync

Главное добавление: единственный статический метод, который запускает процесс, захватывает stdout и stderr, и ожидает завершения без deadlock.

var result = await Process.RunAndCaptureTextAsync("dotnet", "--version");
Console.WriteLine(result.StandardOutput);

Один вызов. Никакого ручного опустошения потоков. Никакого тщательно расположенного WaitForExit. Если вам просто нужно запустить что-то и получить его вывод, это именно тот API, который вы хотите.

Также есть Process.RunAsync для случая, когда нужно ожидать завершения без захвата вывода.

KillOnParentExit

Распространённая проблема с запущенными процессами: если родительский процесс падает или завершается, дочерние процессы продолжают работать как сироты. KillOnParentExit позволяет объявить при запуске процесса, что дочерний процесс должен быть завершён, когда завершается родительский процесс.

Это функциональность, которая существовала в платформо-специфических формах (job objects на Windows, prctl на Linux), но требовала p/invoke или сторонних библиотек для использования из .NET. Теперь это полноценное свойство на ProcessStartInfo.

API на основе SafeProcessHandle

Новая легковесная поверхность API построена вокруг SafeProcessHandle, а не вокруг полного класса Process. Полный класс Process несёт много состояния и его трудно обрезать — путь SafeProcessHandle более дружелюбен к триммеру для приложений, которым нужно минимизировать размер выходных данных (WASM, native AOT).

Полный контроль над наследованием дескрипторов

Обновление также добавляет детальный контроль над тем, какие дескрипторы наследует дочерний процесс и как перенаправляются стандартные дескрипторы. Ранее можно было перенаправлять stdin/stdout/stderr, но нельзя было указать точно, какие дескрипторы наследовать на уровне ОС. Новые API открывают этот контроль.

Почему Это Важно

Класс Process используется в инструментарии, системах сборки, запускателях тестов и любом приложении, которое вызывает другие исполняемые файлы. Старая поверхность API восходила к .NET Framework и показывала свой возраст. Это не ломающее изменение — старые API продолжают работать — но новый код должен предпочитать новую поверхность.

Для обрезанных приложений или сценариев компиляции AOT путь SafeProcessHandle особенно приветствуется. Старый класс Process приносил много кода с тяжёлым использованием рефлексии, что осложняло обрезку.

Оригинальный пост: Process API Improvements in .NET 11

Поделиться:
Просмотреть исходный код этой статьи на GitHub ↗
← .NET 11 Preview 4: Шаблон MCP-Сервера, Runtime-Async Библиотеки, API Процессов
dotnet new WinUI: Создавайте Windows-приложения без Visual Studio →