Reputation: 7919
This problem is probably related to the carriage return character + concurrency, but I can't quite put my finger on it... I have tried plenty of things and I haven't found an answer yet. I would like to at least find a way to correct the error once it has appeared.
Mi executable is a scheduler that prints lines on the command line. At a random moment, the effect shown in the image below (see difference between blue coloured lines) appears and it never leaves. This also appears in a random sequence of events, meaning that in this case it has been after an ADDING but it can also appear after my custom events EXECUTING and ERROR which use other printing functions.
Below you can find the code that exemplifies this behaviour. Note that I am use a token to avoid concurrency.
/// <summary>
/// Console message when the system adds a new execution to the schedule.
/// </summary>
public void PrintAddedExecution(Database.Models.ExecutionSchedule executionDbItem, string messageString)
{
Threading.Monitor.Enter(ConsoleToken);
this.ClearLastLineInConsole();
this.PrintCurrentTime();
System.Console.BackgroundColor = ConsoleColor.DarkBlue;
System.Console.WriteLine(" ADDING [ {0} ] : ", messageString);
System.Console.ResetColor();
System.Console.WriteLine(string.Format(" > exe='{0}' " + \r\n + " > cmd='{1}'", executionDbItem.exe, executionDbItem.cmd));
System.Console.WriteLine();
this.RepeatPrintSystemStatus();
Threading.Monitor.Exit(ConsoleToken);
}
/// <summary>
/// Clears the last written line in the console ("clear" = "fills it with spaces")
/// </summary>
public void ClearLastLineInConsole()
{
System.Console.ResetColor();
System.Console.Write("{0}", \r);
for (int characterCount = 1; characterCount <= System.Console.WindowWidth - 1; characterCount++) {
System.Console.Write(" ");
}
}
/// <summary>
/// Prints the sequence:
/// carriage_return + [ HH:mm ]
/// </summary>
private void PrintCurrentTime()
{
System.Console.BackgroundColor = ConsoleColor.DarkGray;
System.Console.ForegroundColor = ConsoleColor.Black;
System.Console.Write("[ {0:HH:mm:ss} ]", Now);
System.Console.ResetColor();
System.Console.Write(" ");
}
Upvotes: 0
Views: 247
Reputation: 7919
So I finally found a way to avoid this error, although I still have no explanation for it.
The solution is that instead of using this kind of code:
Code with problems:
Console.BackgrounColor = ConsoleColor.MyColor;
Console.WriteLine("Write Something In Console");
Console.ResetColor();
Use always this other way:
"Good" code:
Console.BackgrounColor = ConsoleColor.MyColor;
Console.Write("Write Something In Console");
Console.ResetColor();
Console.WriteLine();
Note that the difference is that I am no longer using WriteLine() if a color change is intervening. Just Write().
I "discovered" this effect empirically, so I gave it a try. After lots of hours of testing it seems to work totally fine.
Upvotes: 1
Reputation: 8878
Try this:
int count = 0;
/// <summary>
/// Console message when the system adds a new execution to the schedule.
/// </summary>
public void PrintAddedExecution(string messageString)
{
Monitor.Enter(ConsoleToken);
if (count >= Console.BufferHeight)
{
Console.Clear();
count = 0;
}
this.PrintCurrentTime();
System.Console.BackgroundColor = ConsoleColor.DarkBlue;
WriteLine(string.Format(" ADDING [ {0} ] : ", messageString));
System.Console.ResetColor();
WriteLine(string.Format(" > exe='{0}' ", "executionDbItem.exe"));
WriteLine(string.Format(" > cmd='{0}'", "executionDbItem.cmd"));
WriteLine();
//this.RepeatPrintSystemStatus();
Monitor.Exit(ConsoleToken);
}
/// <summary>
/// Prints the sequence:
/// carriage_return + [ HH:mm ]
/// </summary>
private void PrintCurrentTime()
{
System.Console.BackgroundColor = ConsoleColor.DarkGray;
System.Console.ForegroundColor = ConsoleColor.Black;
System.Console.Write("[ {0:HH:mm:ss} ]", DateTime.Now);
System.Console.ResetColor();
System.Console.Write(" ");
}
// use this method to write a line so you can keep count of the
// total number of written lines
void WriteLine(string s = null)
{
Console.WriteLine(s);
count++;
}
The key is to clear the buffer when is full, to test that try to comment the Console.Clear();
line.
Upvotes: 1