views:

200

answers:

5

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 has 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.

+1  A: 

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.

Konamiman
But even if I stored this I would still have to switch colors every time while writing to the console. The process of building this string does not take up much time. It's the numerous calls to Console.Write, Console.WriteLine and Console.SetCursorPosition and Console.Foreground = calls that take up all the time. (PS: on fast machines you don't notice this at all)
TimothyP
+1  A: 

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.

Matt Warren
I think I'm going to give this a try...
TimothyP
The downside to this method is that it creates scrollbars so you can scroll to that "invisible" content....
TimothyP
+1  A: 

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.

GregC
+1  A: 

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.

GregC
Hey no :-)For example on the road I'm using a Sony Vaio VGN-P21Z netbook on which it is indeed very slow :p
TimothyP
Your comment does not say what graphics driver you're using.
GregC
GregC
Oh sorry :p I tried the one provided by Vaio and the one provided by Windows. But video and such runs fine on it.
TimothyP
+2  A: 

Is there a way to move your attribute-evaluating logic "outside the loop?" I suspect it's not the quickest part of your code.

GregC
I will check this
TimothyP
Looking at the code again I realize I'm really slowing things down by converting to an array every time... will update and test again. thnx
TimothyP