Reputation: 51
I am trying to write text in the same line with the colour changing mid way through the line. At the moment I have split it into two separate parts, changing the colour each time, just using Console.Write
instead of WriteLine
.
This is fine for procedural operations, but when I run async tasks, I am getting many synchronisation issues.
Is it possible change the text colour mid WriteLine
without using external libraries?
Upvotes: 0
Views: 1144
Reputation: 39152
Try this silly example out using a ConcurrentQueue:
public class Message
{
public List<MessagePart> parts = new List<MessagePart>();
public void Render()
{
parts.ForEach(p => p.Render());
}
public class MessagePart
{
public string text;
public ConsoleColor color;
public MessagePart(string text, ConsoleColor color)
{
this.text = text;
this.color = color;
}
public void Render()
{
Console.ForegroundColor = color;
Console.Write(text);
}
}
}
class Program
{
static bool pause = false;
static bool quit = false;
static ConcurrentQueue<Message> messages = new ConcurrentQueue<Message>();
static void Main(string[] args)
{
Console.WriteLine("Press Space to Pause/UnPause.");
Console.WriteLine("Press Enter to Quit when you are done.");
Console.WriteLine("Press Enter to Start...");
Console.ReadLine();
Task.Run(() => RenderLoop());
Task.Run(() => YellowAndBlue());
Task.Run(() => RedAndBlue());
while (!quit)
{
while (!Console.KeyAvailable)
{
System.Threading.Thread.Sleep(50);
}
switch(Console.ReadKey(false).Key)
{
case ConsoleKey.Enter:
quit = true;
break;
case ConsoleKey.Spacebar:
pause = !pause;
break;
}
}
}
static void YellowAndBlue()
{
Message msg = new Message();
msg.parts.Add(new Message.MessagePart("Yellow", ConsoleColor.Yellow));
msg.parts.Add(new Message.MessagePart(" and ", ConsoleColor.White));
msg.parts.Add(new Message.MessagePart("Blue", ConsoleColor.Blue));
msg.parts.Add(new Message.MessagePart(" make ", ConsoleColor.White));
msg.parts.Add(new Message.MessagePart("Green\r\n", ConsoleColor.Green));
while (!quit)
{
System.Threading.Thread.Sleep(25);
messages.Enqueue(msg);
while (pause)
{
System.Threading.Thread.Sleep(50);
}
}
}
static void RedAndBlue()
{
Message msg = new Message();
msg.parts.Add(new Message.MessagePart("Red", ConsoleColor.Red));
msg.parts.Add(new Message.MessagePart(" and ", ConsoleColor.White));
msg.parts.Add(new Message.MessagePart("Blue", ConsoleColor.Blue));
msg.parts.Add(new Message.MessagePart(" make ", ConsoleColor.White));
msg.parts.Add(new Message.MessagePart("Magenta\r\n", ConsoleColor.Magenta));
while (!quit)
{
System.Threading.Thread.Sleep(25);
messages.Enqueue(msg);
while (pause)
{
System.Threading.Thread.Sleep(50);
}
}
}
static void RenderLoop()
{
Message message;
while (!quit)
{
while (!messages.IsEmpty && !quit)
{
if (messages.TryDequeue(out message))
{
message.Render();
}
while (pause)
{
System.Threading.Thread.Sleep(50);
}
}
if (!quit)
{
messages.Enqueue(new Message() { parts = { new Message.MessagePart("Queue Emptied!\r\n", ConsoleColor.White) } });
System.Threading.Thread.Sleep(100);
}
}
}
}
Output (paused):
Upvotes: 1