C#做更多的线程来加速写入控制台而不会相互干扰
C# Do more threads speed up writing to console without interfering with one another
我目前正在开发一个简单的命令行程序,它有一个像素 class 并将其显示到控制台是最慢的部分。我可以使用多线程来加快写入控制台的速度吗?
你的 Vector2D class 只持有一个 x 和 y 位置。 equals 函数 returns 如果它的 x 和 y 与比较值相同
pixel Renderer函数有点像
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);
}
这会导致像素被放置在错误的点或颜色中吗?
如果不是,最好的方法是什么?
多线程不太可能导致大幅增加,因为 Console
操作全部由并发锁控制,这将导致线程相互节流。
如果您需要加速控制台渲染,我建议实施一个缓冲区(例如 char[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()
。
我目前正在开发一个简单的命令行程序,它有一个像素 class 并将其显示到控制台是最慢的部分。我可以使用多线程来加快写入控制台的速度吗?
你的 Vector2D class 只持有一个 x 和 y 位置。 equals 函数 returns 如果它的 x 和 y 与比较值相同
pixel Renderer函数有点像
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);
}
这会导致像素被放置在错误的点或颜色中吗?
如果不是,最好的方法是什么?
多线程不太可能导致大幅增加,因为 Console
操作全部由并发锁控制,这将导致线程相互节流。
如果您需要加速控制台渲染,我建议实施一个缓冲区(例如 char[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()
。