Класс .NET Console и его реализация по умолчанию TextWriter (доступная как Console.Out и неявно, например, Console.WriteLine()) не сигнализируют о какой-либо ошибке, когда приложение передает свой вывод в другую программу, а другая программа завершает или закрывает трубку до завершения работы приложения. Это означает, что приложение может работать дольше, чем необходимо, записывая вывод в черную дыру.
Как я могу обнаружить закрытие другого конца переадресации?
Ниже приведено более подробное объяснение:
Вот пара примеров программ, которые демонстрируют проблему. Produce довольно медленно печатает множество целых чисел, чтобы имитировать эффект вычисления:
using System;
class Produce
{
static void Main()
{
for (int i = 0; i < 10000; ++i)
{
System.Threading.Thread.Sleep(100); // added for effect
Console.WriteLine(i);
}
}
}
Consume только считывает первые 10 строк ввода и затем выходит:
using System;
class Consume
{
static void Main()
{
for (int i = 0; i < 10; ++i)
Console.ReadLine();
}
}
Если эти две программы скомпилированы, а вывод первого - со вторым, так:
Produce | Consume
... можно заметить, что Produce продолжает работать после завершения Consume.
В действительности моя программа Consume - это стиль Unix head, а моя программа Produce печатает данные, которые дорого рассчитать. Я хотел бы завершить вывод, когда другой конец канала закрыл соединение.
Как это сделать в .NET?
(Я знаю, что очевидной альтернативой является передача аргумента командной строки для ограничения вывода и действительно того, что я сейчас делаю, но я все равно хотел бы знать, как это сделать, поскольку я хочу быть в состоянии чтобы сделать более настраиваемые суждения о том, когда прекратить чтение, например, проложить через grep до head.)
UPDATE:. Это выглядит ужасно, как реализация System.IO.__ConsoleStream в .NET жестко запрограммирована для игнорирования ошибок 0x6D (ERROR_BROKEN_PIPE) и 0xE8 (ERROR_NO_DATA). Вероятно, это означает, что мне нужно повторно реализовать консольный поток. Вздох...)