首页 > 解决方案 > C#做更多的线程加速写入控制台而不相互干扰

问题描述

我目前正在开发一个简单的命令行程序,它有一个像素类,并将其显示到控制台是最慢的部分。我可以使用多个线程来加快写入控制台的速度吗?

你的 Vector2D 类只保存 ax 和 y 位置。如果 x 和 y 与比较值相同,则 equals 函数返回

像素渲染器功能看起来有点像

public Vector2D location { get; private set; }
public char pixel { get; private }
public ConsoleColor FG { get; private }
public ConsoleColor BG { get; private }
public int layer { get; private }
public int ID { get; private set; }


public void renderer()
        {
            foreach (Pixel pixel in GlobalPixels)
            {
                if((this.ID != pixel.ID) && (this.location == pixel.location))
                {
                    if (this.layer < pixel.layer) return;
                }
            }

            Console.SetCursorPosition(location.x, location.y);
            Console.ForegroundColor = FG;
            Console.BackgroundColor = BG;
            Console.Write(pixel);
        }

穿线会导致像素被放置在错误的位置或颜色上吗?

如果不是,最好的方法是什么?

标签: c#multithreadingconsole-application

解决方案


多个线程不太可能导致大幅增加,因为Console操作都由并发锁控制,这将导致线程相互限制。

如果您需要加快控制台渲染速度,我建议您实现一个缓冲区(例如 achar[80,25]或类似的东西)并在那里写入您的像素。完成像素写入后,将整个缓冲区一次性复制到控制台,顺序从上到下,从左到右。控制台在按顺序写入行时要快得多,而在您必须SetCursorPosition重复使用时则较慢。

这是一个简单的示例,可以帮助您入门:

public class BufferedConsole
{
    private class Cell
    {
        public char Pixel;
        public ConsoleColor ForegroundColor;
        public ConsoleColor BackgroundColor;
    }

    static private Cell[,] _buffer = new Cell[80, 25];

    static BufferedConsole()
    {
        Clear();
    }

    static void Clear()
    {
        for (int row = 0; row < 25; row++)
        {
            for (int col = 0; col < 80; col++)
            {
                _buffer[col, row] = new Cell
                {
                    ForegroundColor = ConsoleColor.Black,
                    BackgroundColor = ConsoleColor.Black,
                    Pixel = '?'
                };

            }
        }
        Refresh();
    }

    public static void Plot(int x, int y, char pixel, ConsoleColor foreColor, ConsoleColor backColor)
    {
        var cell = _buffer[x, y];
        cell.Pixel = pixel;
        cell.ForegroundColor = foreColor;
        cell.BackgroundColor = backColor;
    }

    public static void Refresh()
    {
        Console.SetCursorPosition(0, 0);
        ConsoleColor lastForeColor = ConsoleColor.White;
        ConsoleColor lastBackColor = ConsoleColor.Black;

        Console.CursorVisible = false;

        for (var row = 0; row < 25; row++)
        {
            for (var col = 0; col < 80; col++)
            {
                var cell = _buffer[col, row];
                if (lastForeColor != cell.ForegroundColor)
                {
                    Console.ForegroundColor = cell.ForegroundColor;
                    lastForeColor = cell.ForegroundColor;
                }

                if (lastBackColor != cell.BackgroundColor)
                {
                    Console.BackgroundColor = cell.BackgroundColor;
                    lastBackColor = cell.BackgroundColor;
                }

                Console.Write(cell.Pixel);
            }
            Console.WriteLine();
        }
        Console.CursorVisible = true;
    }

}

现在只需替换​​这个:

Console.SetCursorPosition(location.x, location.y);
Console.ForegroundColor = FG;
Console.BackgroundColor = BG;
Console.Write(pixel);

有了这个:

BufferedConsole.Plot(location.x, location.y, pixel, FG, BG);

...完成后,请致电Refresh().


推荐阅读