Reputation: 19179
I'm making a test console application. This application runs a void task (I can't change this fact), and for it to remain opened I insert Console.ReadLine
at end of Main method.
Is there any way to consume each key being pressed from other threads? I tried the following but call to Peek is blocking the thread.
loop = Task.Run(async () =>
{
var input = Console.In;
while (running)
{
int key = input.Peek(); // blocks here forever
if (key == -1)
{
await Task.Delay(50);
}
else
{
input.Read();
if ((ConsoleKey)key == ConsoleKey.Enter)
{
Completed?.Invoke();
}
else
{
OnKeyDown((ConsoleKey)key);
}
// todo how to intercept keyup?
}
}
});
This is the main method
static void Main(string[] args)
{
GrpcEnvironment.SetLogger(new Grpc.Core.Logging.ConsoleLogger());
//setup MagicOnion and option.
var service = MagicOnionEngine.BuildServerServiceDefinition(isReturnExceptionStackTraceInErrorDetail: true);
var server = new global::Grpc.Core.Server
{
Services = { service },
Ports = { new ServerPort("localhost", 12345, ServerCredentials.Insecure) }
};
// launch gRPC Server.
server.Start();
// and wait.
Console.ReadLine();
}
what I want is basically to have a keyboard key pressed event listener on another thread.
I also tried global keyboard hooks but that does not work for console application.
Upvotes: 2
Views: 2440
Reputation: 4282
You consider just trying something like this?
Make sure to try running this from an actual console as my mileage with VS 2017 varied on CTRL-C working in the IDE. (I should have mentioned this uses C# 7.2 - for async main)
class Program
{
static async Task Main()
{
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (sender, args) => cts.Cancel();
Console.WriteLine("Press CTRL-C to Exit");
// Start you server here
while (!cts.IsCancellationRequested)
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey(true);
Console.WriteLine($"Read: {key.KeyChar}");
}
await Task.Delay(50, cts.Token);
}
}
}
Upvotes: 1
Reputation: 19179
I decided to put this instead of Console.ReadLine
at end of Main method.
while (true) Task.Delay(1000).Wait(); // console.ReadLine doesn't let us to read from console in other threads.
And then I can do
loop = Task.Run(() =>
{
while (running)
{
var key = Console.ReadKey(true).Key;
if (key == ConsoleKey.Enter)
{
Completed?.Invoke();
}
else
{
OnKeyDown(key);
}
// todo how to intercept keyup?
}
});
by pressing enter, our application wont close but this is a test application and exit with enter is not our requirement.
but If someone still knows an anwer with Console.ReadLine
I appreciate to know it.
Upvotes: 1