Reputation: 3834
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
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