I have created a 24 hour clock and I want to be able to reset it to 00:00:00 when the enter key is pressed. The clock itself functions fine but I am unable to include the reset functionality properly
static void Main(string[] args)
{
Clock _clock = new Clock();
ConsoleKeyInfo _key = Console.ReadKey();
while (true)
{
Console.WriteLine(_clock.Time);
_clock.Tick();
System.Threading.Thread.Sleep(1000);
if (_key.KeyChar == (char)13)
{
_clock.Reset();
}
}
The problem is, you only read the current keypress once- at the very beginning of your program. Console.Readkey() will wait for you to press a key, then return the key you pressed (which then gets stored in _key). Because you never read another keypress inside the loop, _key will never change.
Of course, you can't simply call Console.ReadKey() inside the loop or the program will pause and wait for you to press a key during every iteration, so you'll want to follow the advice Aybe linked to in his comment.
Related
I have pause functionality in my application that I would like to interact with via keypresses in the System.Console window, and so the aptly-named ConsoleKey.Pause seems correct to use since the documentation says it corresponds to "the PAUSE key."
But whenever I press the key explicitly labeled Pause on my keyboard, Console.ReadKey never does anything:
while (_isOpen)
if (Console.ReadKey(false).Key == ConsoleKey.Pause)
_engine.TogglePause();
So what does ConsoleKey.Pause represent, and how might I trigger it? Or should I just invent my own shortcuts?
try below code:
while (_isOpen)
{
//Do you works need
if (Console.KeyAvailable)
{
var consoleKey = Console.ReadKey(true); //if true then keeps the key from
//the console
if (consoleKey.Key == ConsoleKey.Pause)
{
_engine.TogglePause();
}
}
}
I am creating a console application that shows simple animations with text. I have a thread that waits for the user to press "Up Arrow", "Down Arrow" and "Enter/Carriage Return/Return". It seems that the user must press any of these keys multiple times for the key to be registered, however sometimes the key is registered instantly. I assume, as you would too; that this is a problem with my code. I had a power failure last week and it wiped out part of my project, whilst rewriting my code this problem appeared.
I have tried using
if(Console.KeyAvailable == true && Console.Readkey().key == [one of the three keys])
to no avail.
I tried removing (Memory memory) from the class leaving it just
private static void GetKeyboardInput() {}
but this didn't seem to have any effect. BTW, when I did that the thread was declared like this
Thread getkey = new Thread(GetKeyboardInput);
perhaps I am doing this part wrong?
Here is some of my code neutered for size...
// declare listener thread and start it.
Thread GetKey = new Thread(() => GetKeyboardInput(memory));
GetKey.Start();
while (GetKey.ThreadState == ThreadState.Running)
{ Animate(memory); } // this is the text animation, ---> Menuitem <---
// the arrows move in and out from the menu item
Animate(memory); runs in the current tread, so it isn't the culprit, correct?
// This is the code that the thread runs
// Memory class contains all stored values for this program
private static void GetKeyboardInput(Memory memory)
{
while (Console.ReadKey().Key != ConsoleKey.Enter)
{
if (Console.ReadKey().Key == ConsoleKey.UpArrow)
{
// move up. There is more code here but not relevant
}
if (Console.ReadKey().Key == ConsoleKey.DownArrow)
{
// Move Down. Same as before
}
}
Thread.CurrentThread.Abort();
}
I expect that in less than 1000ms after a key is pressed that the revelant code within the if statements gets executed and the screen will show a change to the user, if any.
Actual results are that sometimes the program reacts to user input instanly, and other times the user has to press the key multiple times to register a change. This is not session dependent either, at any time during execution both of these above problems will/can be present.
The problem is that you're calling Console.ReadKey() multiple times: once to check that it's not enter, again to check whether it's UpArrow, yet again to check whether it was DownArrow. You probably want to read it once, and store it in a variable.
// This is the code that the thread runs
// Memory class contains all stored values for this program
private static void GetKeyboardInput(Memory memory)
{
while (true)
{
var key = Console.ReadKey().Key;
if (key == ConsoleKey.Enter)
{
break;
}
else if (key == ConsoleKey.UpArrow)
{
// move up. There is more code here but not relevant
// meaning these values effect the animation and nothing else
}
else if (key == ConsoleKey.DownArrow)
{
// Move Down. Same as before
}
}
// No need to call Thread.Abort - exiting this method does the same
}
I need to make it to where my code will only exit the loop when the key that is pressed, is released. I am doing this is console and will need to stay in console.
Here is an example of the code.
ConsoleKeyInfo = ki;
while (true)
{
ki = Console.ReadKey();
if (ki.Key == ConsoleKey.A)
{
Console.Write("A");
}
}
As you can see above, when the A key is pressed, it will write A in the console. If you hold down the A key, it will continuously write A.
What I'm wanting is for the console to write A ONCE until the A key is released. Then, if you press A again, it will print again.
I've thought about using "KeyUp" but I'm not able to use it on a console application. But something that would accomplish the following...
ConsoleKeyInfo = ki;
while (true)
{
ki = Console.ReadKey();
if (ki.Key == ConsoleKey.A)
{
//I know the following isn't actually code, but it's explaining what I want to happen.
do (onKeyRelease)
{
Console.Write("A");
}
}
}
Basically, I'm wanting only one thing to happen when the loop when a key is pressed until the key is released. When the key is released, the loop will start again.
Please note that I am using this idea for a Text-Based RPG game. So waiting until another key is pressed (including adding another Console.ReadKey() to the end) would not be ideal.
1st Suggestion - Have you tried "break" the loop when the console has displayed the "A"?
2nd Suggestion -
ConsoleKeyInfo = ki;
var alreadyPressed = false
while (true)
{
ki = Console.ReadKey();
if (ki.Key == ConsoleKey.A && !alreadyPressed)
{
Console.Write("A");
alreadyPressed = true;
}}`
Store last pressed key and print character only when it is different from the last pressed key.
I have a console application with two threads, one is doing repetitive time consuming work, the other is checking to see if the user has pressed the ESC key. If the ESC key was pressed, the time consuming work thread is paused, an "are you sure" message appears, and if yes is selected, the time consuming work thread finishes its current loop then exits.
The code I have to check for a key-press is using a lot of CPU resources due to the while (!breakCurrentOperation(work)) ; loop. How can I prevent this from happening?
Code:
public void runTimeConsumingWork()
{
HardWork work = new HardWork();
Thread workerThread = new Thread(() => work.StartWorking());
workerThread.Start(); // Start the hard work thread
while (!workerThread.IsAlive) ; // Hault untill Thread becomes Active
// Check if the user wants to stop the hard work
while (!breakCurrentOperation(work)) ;
// Cancle the hard work
work.Stop();
// Notify the User
UserInterfaceController.WriteToConsole("Operation Cancled...");
}
public static bool breakCurrentOperation(HardWork work)
{
if (Console.KeyAvailable)
{
var consoleKey = Console.ReadKey(true);
if (consoleKey.Key == ConsoleKey.Escape)
{
work.Pause(); // Pause
UserInterfaceController.WriteToConsole("Do you want to stop the current process? \nType s to stop or c to continue.");
string input = Console.ReadLine();
if (input == "c" || input == "C")
{
work.Pause(); // Unpause
return false; // Continue
}
else if (input == "s" || input == "S")
{
return true; // Break the loop
}
else
{
UserInterfaceController.WriteToConsole("Error: Input was not recognized, the current process will now continue. Press Esc to stop the operation.");
work.Pause(); // Unpause
}
}
}
return false;
}
If I place a Thread.Sleep(2000) in the main console UI thread, CPU usage goes way down, but the application becomes unresponsive with a 2 second delay.
Do you really have to constantly poll for input? If you are waiting for input in a separate thread, just use the Console.ReadKey. It will block the input thread, but your other thread will keep processing. You don't seem to be doing anything else on the input thread, so blocking shouldn't be an issue.
Look like your esc key press check logic running in end less loop due to while loop. Due to this the function keep utilizing the system resource.
To overcome this please use some delay in your loop using Thread.Sleep. 1 second delay will improve lot of performance.
I'm trying to figure out how I can use Console.ReadLine and a timer. My console program is designed to run a long process automatically, with this process restarting every 30 seconds after the previous process completed. I want to give the user the ability to break the auto-run by typing a command though. If I use Console.ReadLine() though, it will wait until the user enters something, whereas I want the program to continue on through a loop if nothing is entered within 30 seconds. . . Any thoughts??
For example:
RunProcess > Wait 30s for User Input. If none: Continue Loop
Thanks a lot!
You could run your timer on a separate thread. When the user enters text, store it in a variable that is accessible to both threads. When the timer ticks, see if anything is entered and continue accordingly.
Be sure to be thread safe :-)
EDIT:
You can use a System.Threading.Timer to tick every 30 seconds and in its callback method, check if the text has been set.
Don't use Console.ReadLine() but check if Console.KeyAvailable is true and then read Console.ReadKey() to check for exit condition.
Try this example code
class Program
{
static bool done;
static void Main(string[] args)
{
int count = 0;
done = false;
while (!done)
{
Thread.Sleep(2000);
count++;
Console.WriteLine("Calculation #" + count.ToString());
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.Escape)
{
done = true;
}
}
}
Console.WriteLine();
Console.WriteLine("end");
}
}