Reputation: 619
I'm trying to make a console application. I want the ". . ." after "Press any key to exit" to blink.
The blinking is working fine and all, but now my Console.ReadKey() is unreachable code.
I'm just wondering if there is anyway to let the Console.ReadKey() line be reached, or where I would move it to be able to let it be run?
static void Main(string[] args)
{
string blinkExit = ". . ."; //Variable for blinking periods after 'exit'
Console.Write("\n\nPress any key to exit"); //Displays a message to press any key to exit in the console
while (true)
{
WriteBlinkingText(blinkExit, 500, true);
WriteBlinkingText(blinkExit, 500, false);
}
Console.ReadKey();
}
private static void WriteBlinkingText(string text, int delay, bool visible)
{
if (visible)
Console.Write(text);
else
for (int i = 0; i < text.Length; i++)
Console.Write(" ");
Console.CursorLeft -= text.Length;
System.Threading.Thread.Sleep(delay);
}
Upvotes: 0
Views: 1309
Reputation: 15334
Imagine threads as workers, when you use the console application, you are working on one thread, and by using a loop which doesn't end, you are essentially stopping any other task from occurring from that point onwards because the thread is busy looping!
To solve the problem you need to place a trigger of sorts in the loop which is going to exit once a key is pressed. I've demonstrated a simple way to do this below.
Examine the code, you'll find that I've used a new class called Interlocked
, the reason I used this is to avoid any thread safety issues, thread safety is a deep topic, and isn't something I want to be trying to explain in a few sentences, but the idea is that any resources being shared between two different threads, must be locked. You'll also find a lambda expression, these are all intermediate topics, and trying to learn them now is going to achieve one thing... a headache!
private static long _isKeyPressed;
private static void Main()
{
// Create a new Thread and Start it.
new Thread(() =>
{
// Variable for blinking periods after 'exit'
const string blinkExit = ". . .";
// Displays a message to press any key to exit in the console
Console.Write("\n\nPress any key to exit");
// Run until no keys are pressed.
while (Interlocked.Read(ref _isKeyPressed) == 0)
{
WriteBlinkingText(blinkExit, 500, true);
WriteBlinkingText(blinkExit, 500, false);
}
}).Start();
Console.ReadKey();
// Once a key has been pressed, increment the value of _isKeyPressed to 1.
// This will indicate to the thread running above that it should exit it's loop.
// as _isKeyPressed is no longer equal to 0.
Interlocked.Increment(ref _isKeyPressed);
}
private static void WriteBlinkingText(string text, int delay, bool visible)
{
if (visible) Console.Write(text);
else
{
for (int i = 0; i < text.Length; i++)
{
Console.Write(" ");
}
}
Console.CursorLeft -= text.Length;
Thread.Sleep(delay);
}
Upvotes: 0
Reputation: 755577
It seems like you just want this text to blink until a key is pressed by the user. If that is the case then why not just loop until there is a key available to be read?
while (!Console.KeyAvailable)
{
WriteBlinkingText(blinkExit, 500, true);
WriteBlinkingText(blinkExit, 500, false);
}
This avoids all of the nasty issues that can come up with using multiple threads
Upvotes: 3
Reputation: 20140
just change your while code with this
Task.Factory.StartNew(() =>
{
while (true)
{
WriteBlinkingText(blinkExit, 500, true);
WriteBlinkingText(blinkExit, 500, false);
}
});
pressing any key will close the console
Upvotes: 2