1

当我偶然发现 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,6gb DDR3,所以存储不应该是问题......有人知道可能出了什么问题吗?

4

2 回答 2

5

导致异常的 API 函数是 ReadConsoleOutput()。SDK 文档有一些相关的小字:

lpBuffer:

指向接收从控制台屏幕缓冲区读取的数据的目标缓冲区的指针。此指针被视为 CHAR_INFO 结构的二维数组的原点,其大小由 dwBufferSize 参数指定。数组的总大小必须小于 64K

我将相关短语加粗。当您的程序尝试滚动超过 200 行时(201 x 80 x 4 = 64320 字节,奇怪的是与 65536 相比有点偏离),您的程序将会爆炸。这可以说是 Console.MoveBufferArea() 中的一个错误,它不会检查此限制,也不会尝试解决它,这很容易做到。您可以在 connect.microsoft.com 上报告错误

现在,您必须限制行数,以使缓冲区大小不超过限制。

于 2009-12-08T04:02:31.897 回答
0

控制台不仅仅是另一个窗口。它的真正目的是允许双向输入、shell 级别重定向等,并且当您尝试执行此类操作时可能会遇到一些奇怪的问题。这主要是因为您使用的是文件流缓冲区,而不仅仅是屏幕上的文本。

您是否考虑过制作一个 Window 来托管您的“控制台”信息,因为您显然正在执行非标准输出流?您可以将您的控制台 I/O 重定向到您自己的流(这是在 VB.NET 中执行此操作的示例),然后使用 RichTextBox 之类的东西自己在窗口中显示它。

如果您正在使用“反向”控制台,那么您显然没有使用命令行重定向工具或输入机制 - 在这种情况下,自定义窗口可能是一种更好的方法。

于 2009-12-08T02:04:52.523 回答