Как Console.ReadLine из одного потока и использовать ConsoleKeys из другого потока? - PullRequest
0 голосов
/ 28 января 2019

Я делаю тестовое консольное приложение.Это приложение выполняет задачу void (я не могу изменить этот факт), и чтобы оно оставалось открытым, я вставляю Console.ReadLine в конце метода Main.

Есть ли способиспользовать каждую нажатую клавишу из других потоков?Я попробовал следующее, но вызов 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();
}

, что я хочу, чтобы в основном было нажатой клавишей прослушивания событий на слушателе событийдругой поток.


Я также пытался глобальные клавиатурные хуки , но это не работает для консольного приложения.

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Вы рассматриваете возможность попробовать что-то подобное?

Обязательно попробуйте запустить его с реальной консоли, так как мой пробег с VS 2017 варьировался в зависимости от CTRL-C, работающего в IDE.(Я должен был упомянуть, что это использует C # 7.2 - для асинхронной основной)

    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);
            }
        }
    }
0 голосов
/ 28 января 2019

Я решил поставить это вместо Console.ReadLine в конце метода Main.

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, я рад знать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...