Caching System.Console output
We have some methods that output a lot of coloured text to the Console.
It's actually a menu that is built by looping through a collection of data.
Because we are writing item by item (and one line contains many items in different colours), this process is rather slow on low-end and mid-end machines. On those machines you can see each line being written one by one and it's rather frustrating for the end user.
This menu ha开发者_JAVA技巧s to be displayed many times so I'm wondering if I can't just "cache" this output somehow. If there was no coloured text I'd simply store the output in a string and write it in one go, but I don't want to lose colour information.
Any suggestions?
Update: Just to give an idea of how intensive the output is: Update 2: Updated the sloppy code, but still want to buffer the output somehow. MoveBufferArea proves to be a partial solution (it creates unwanted scrollbars)
DefaultBanner();
WriteLine("Available tests:\n", ConsoleColor.White);
var methodNames = methods.Select(m => ((TestAttribute)m.GetCustomAttributes(false)[0]).Name).ToArray();
int vertical = 0;
for (int i = 1; i <= methods.Length; i++)
{
if (i > methods.Length / 2)
{
Console.SetCursorPosition(40, 4 + vertical++);
}
Write("(");
Write(i, ConsoleColor.Yellow);
WriteLine(") {0:00}", methodNames[i - 1]);
}
Write("\n(");
Write(items.Count + 1, ConsoleColor.Yellow);
Write(") Set address | (");
Write(items.Count + 2, ConsoleColor.Yellow);
Write(") View Log | (");
Write(items.Count + 3, ConsoleColor.Yellow);
Write(") Open Log directory \n(");
Write(items.Count + 4, ConsoleColor.Yellow);
Write(") Open configuration | (");
Write(items.Count + 5, ConsoleColor.Yellow);
Write(") View current configuration | (");
Write(items.Count + 6, ConsoleColor.Yellow);
WriteLine(") Quit");
Write("\nYour selection: ");
int command = 0;
while (!ConsoleReader<int>.TryReadValueInRange(1, items.Count + 6,out command));
return command;
The Write methods are simply helper methods that encapsulate some behaviour of the System.Console class so we wouldn't have to keep setting the colour.
Maybe you could something clever using the MoveBufferArea function. What about if you had a area of the buffer that was not currently visible to the user. You could create your buffer\menu there and then copy the whole region to a part of the visible buffer in one go. I don't know how much control you have over the visible/non-visible areas of the buffer and if you can use them like this, it's just a suggestion.
The only other option I can think of is creating your own control that mimics the console. You could then make allow buffered reads/writes or only refresh after you've made several changes. But this could be a lot of extra work.
Is there a way to move your attribute-evaluating logic "outside the loop?" I suspect it's not the quickest part of your code.
I don't know if it is possible for your project, but one option is using some type of markup language to store the color inside the string itself, for example <yellow>Text in yellow</yellow>
(or your could use plain CSS selectors, or whatever). This way you could use a plain string cache.
By the way remember that the .NET Framework already implements one such cache: see String.Intern and String.IsInterned.
Keep in mind that Console is a configurable device, meaning that you can write your own (though I don't recommend it). There is a way to specify in config file which class does Tracing and which class does Debug output.
Is there a way to ask your clients to make sure they are running hardware-accelerated graphics (check the drivers)? If they are running with VGA-Only default Microsoft driver, then console will be painfully slow.
精彩评论