Reputation: 131
I want to constantly wait for a key combination to be pressed in my console application, but the way I am currently doing it seems to use a lot of CPU while the process is running.
For such a basic task it feels like there should be a better way to do this, but I'm unsure of what that is, I profiled my application with dotTrace and found that the only hot spot was this code below.
while (true)
{
if (!Console.KeyAvailable)
{
continue;
}
var input = Console.ReadKey(true);
if (input.Modifiers != ConsoleModifiers.Control)
{
continue;
}
if (input.Key == ConsoleKey.S)
{
Server?.Dispose();
}
}
Upvotes: 3
Views: 3248
Reputation: 27
You only need this before finish Main(string[] args)
private static void Main(string[] args)
{
//call method for daemon before while
while (true)
{
Thread.Sleep(1000);
}
}
Upvotes: 0
Reputation: 5353
No busy waiting is needed. Console.ReadKey()
will block until there is a key press available, with basically no CPU usage. Thus, you don't need to check Console.KeyAvailable
over and over again.
while (true)
{
// DO NOT INTERCEPT KEY PRESSES!
//IF CTRL+S IS FORWARDED TO THE CONSOLE APP, WEIRD THINGS WILL HAPPEN.
var input = Console.ReadKey(false);
if (input.Modifiers != ConsoleModifiers.Control)
{
continue;
}
if (input.Key == ConsoleKey.S)
{
Server?.Dispose();
}
}
Upvotes: 1
Reputation: 12849
If you are fine using standard Ctrl+C for exit instead of Ctrl+S you can use simple ReadKey
. And make sure TreatControlCAsInput
is set, oterwise, the application will just be killed.
static void Main(string[] args)
{
// important!!!
Console.TreatControlCAsInput = true;
while (true)
{
Console.WriteLine("Use CTRL+C to exit");
var input = Console.ReadKey();
if (input.Key == ConsoleKey.C && input.Modifiers == ConsoleModifiers.Control)
{
break;
}
}
// Cleanup
// Server?.Dispose();
}
Upvotes: 3
Reputation: 24515
Instead of watching this in a loop, use the keypress event to check each time a key is pressed.
This means you only check once for each key press.
Edit: I missed the console app part but you can read the line like this:
from: https://www.dotnetperls.com/console-readline
using System;
class Program
{
static void Main()
{
while (true) // Loop indefinitely
{
Console.WriteLine("Enter input:"); // Prompt
string line = Console.ReadLine(); // Get string from user
if (line == "exit") // Check string
{
break;
}
Console.Write("You typed "); // Report output
Console.Write(line.Length);
Console.WriteLine(" character(s)");
}
}
}
Upvotes: 2
Reputation: 631
I think you should use Thread.Sleep
while (true)
{
Thread.Sleep(100);
if (!Console.KeyAvailable)
{
continue;
}
var input = Console.ReadKey(true);
if (input.Modifiers != ConsoleModifiers.Control)
{
continue;
}
if (input.Key == ConsoleKey.S)
{
Server?.Dispose();
}
}
Upvotes: 0