Странная консоль MoveBufferArea IOException

Я строил "обратную консоль" (чтобы написанные строки добавлялись вверху, а не внизу), когда я наткнулся на очень странное поведение метода Console.MoveBufferArea:

    static void Main()
    {
        for (var _linesWritten = 0; _linesWritten < 1000; _linesWritten++)
        {
            var _height = Math.Min(Console.BufferHeight-1, _linesWritten);
            Console.MoveBufferArea(0, 0, Console.BufferWidth, _height, 0, 1);
            Console.SetCursorPosition(0, 0);
            Console.WriteLine("Line {0} aaaaaaaaaa", _linesWritten);
            Console.ResetColor();
        }
    }

Когда я вызываю его фиксированное количество раз, оно выдает исключение System.IO.IOException, говорящее: "Недостаточно памяти для обработки этой команды". Я понял, что это зависит от объема буферной области, которая перемещается. Количество строк, написанных до возникновения исключения, изменяется по мере изменения свойства Console.BufferWidth.

Скриншот

Я работаю под управлением Windows 7 x64 @ Corei7, 6 ГБ DDR3, так что с хранилищем проблем не будет.... Кто-нибудь знает, что может быть не так?

2 ответа

Решение

API-функция, вызывающая исключение, - ReadConsoleOutput(). Документ SDK содержит несколько значимых мелочей:

lpBuffer:

Указатель на буфер назначения, который получает данные, считанные из буфера экрана консоли. Этот указатель рассматривается как источник двумерного массива структур CHAR_INFO, размер которого определяется параметром dwBufferSize. Общий размер массива должен быть менее 64 КБ.

Я выделил соответствующую фразу. Ваша программа будет бомбить, когда она попытается прокрутить более 200 строк (201 x 80 x 4 = 64320 байт, что немного странно с 65536). Возможно, это ошибка в Console.MoveBufferArea(), она не проверяет это ограничение и не пытается обойти его, что было бы легко сделать. Вы можете сообщить об ошибке на connect.microsoft.com

На данный момент вам нужно ограничить количество строк, чтобы размер буфера не превышал этот предел.

Консоль - это не просто другое окно. Он действительно предназначен для двунаправленного ввода, перенаправления на уровне оболочки и т. Д. И может иметь некоторые странные проблемы при попытке сделать что-то подобное. В основном это связано с тем, что вы работаете с буфером файловых потоков, а не только с текстом на экране.

Рассматривали ли вы просто создание окна для размещения вашей "консольной" информации, поскольку вы, очевидно, делаете нестандартный поток вывода? Вы можете просто перенаправить ваш консольный ввод / вывод в свой собственный поток ( вот пример того, как это делается в VB.NET), и отобразить это в окне самостоятельно, используя что-то вроде RichTextBox.

Если вы используете "перевернутую" консоль, вы, очевидно, не используете средства перенаправления командной строки или механизмы ввода - в этом случае пользовательское окно, вероятно, является более подходящим подходом.

Другие вопросы по тегам