Joe
Joe

Reputation: 3834

How can I collect key presses while time is passing?

I'd like to write a loop that collects key presses (from the keyboard) and does an action every second or so. There would be some way of reading from the keyboard:

whenever (Console.KeyPressed != null) {
    input_buffer.Add(Console.KeyPressed);
}

And there would be some loop happening:

while (!done) {
    if (input_buffer.NotEmpty()) { do_stuff(input_buffer.Pop()); }
    do_other_stuff();
    wait(0.5 seconds);
}

So if the user presses a key, it gets dealt with during the next update. If they don't press a key, the next update happens anyhow.

Upvotes: 3

Views: 234

Answers (1)

Christoffer Lette
Christoffer Lette

Reputation: 14816

If you're on .Net 4 you can use the code below. It uses ConcurrentQueue for storing the keypresses, ManualResetEventSlim for signaling, and Task from the Task Parallel Library for running the two code parts asynchronously.

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Test
{
    public class Program
    {
        private static ConcurrentQueue<ConsoleKeyInfo> _keypresses = new ConcurrentQueue<ConsoleKeyInfo>();
        private static ManualResetEventSlim _stopEvent = new ManualResetEventSlim();

        public static void Main()
        {
            Console.TreatControlCAsInput = true;

            var keyReaderTask = Task.Factory.StartNew(ReadKeys);
            var keyProcessingTask = Task.Factory.StartNew(ProcessKeys);

            _stopEvent.Wait();
            keyReaderTask.Wait();
            keyProcessingTask.Wait();
        }

        public static void ReadKeys()
        {
            while (true)
            {
                var keyInfo = Console.ReadKey(true);

                if (keyInfo.Modifiers == ConsoleModifiers.Control && keyInfo.Key == ConsoleKey.C)
                {
                    break;
                }

                _keypresses.Enqueue(keyInfo);
            }

            _stopEvent.Set();
        }

        public static void ProcessKeys()
        {
            while (!_stopEvent.IsSet)
            {
                if (!_keypresses.IsEmpty)
                {
                    Console.Write("Keys: ");

                    ConsoleKeyInfo keyInfo;
                    while (_keypresses.TryDequeue(out keyInfo))
                    {
                        Console.Write(keyInfo.KeyChar);
                    }
                    Console.WriteLine();
                }

                _stopEvent.Wait(1000);
            }
        }
    }
}

Upvotes: 2

Related Questions