我正在制作一个测试控制台应用程序。此应用程序运行 void 任务(我无法更改此事实),为了使其保持打开状态,我在Main方法的末尾插入了Console.ReadLine
。
有没有办法使用其他线程所按下的每个键?我尝试了以下操作,但对Peek的调用阻止了该线程。
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?
}
}
});
这是主要方法
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();
}
我想要的基本上是在另一个线程上按下键盘按键的事件监听器。
我也尝试过global keyboard hooks,但这不适用于控制台应用程序。
答案 0 :(得分:1)
我决定将其放置在Main方法的末尾,而不是Console.ReadLine
。
while (true) Task.Delay(1000).Wait(); // console.ReadLine doesn't let us to read from console in other threads.
然后我可以做
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?
}
});
通过按Enter键,我们的应用程序不会关闭,但这是一个测试应用程序,按Enter键退出不是我们的要求。
但是如果有人仍然知道Console.ReadLine
的问题,我很高兴知道。
答案 1 :(得分:1)
您考虑只是尝试这样的事情?
请确保尝试从实际的控制台运行此程序,因为我在IDE中使用CTRL-C时使用VS 2017的里程数有所不同。 (我应该提到,这使用C#7.2-用于异步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);
}
}
}