I am required to write a program that prints out numbers until I write in the console window a simple string "stop". The numbers are supposed to go on infinitely until the condition is met.
I tried:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
internal class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000000000;)
{
Console.WriteLine(i);
string a = Console.ReadLine();
if (a == "stop")
{
break;
}
i ;
}
}
}
}
But, there is a delay waiting for my input every time, it's not constant.
CodePudding user response:
You are asking for a non blocking console read. THats not simple.
One way is to peek to see if a key is available to read
int number = 0;
while (true)
{
Console.WriteLine(number);
number ;
if (Console.KeyAvailable)
{
var s = Console.ReadLine();
if (s == "stop")
break;
}
}
CodePudding user response:
To interrupt the Console.Readline call I used a solution by Gérald Barré (https://www.meziantou.net/cancelling-console-read.htm). We need to import a method CancelIoEx to cancel the ReadLine request. Using GetStdHandle as a way to identify what input request we want to cancel.
If a key is pressed the program will send an input request, but the program will continue as normal if the user waits too long.
Edit: Included further explaination as Lance mentioned I should've done.
using System.Runtime.InteropServices;
const int STD_INPUT_HANDLE = -10;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);
int val = 0;
bool run = true;
bool typing = false;
while(run)
{
if(!typing)
{
Console.WriteLine(val);
val ;
if(Console.KeyAvailable)
{
typing = true;
}
}
else
{
var read = false;
Task.Delay(10000).ContinueWith(x =>
{
if(!read)
{
var handle = GetStdHandle(STD_INPUT_HANDLE);
CancelIoEx(handle, IntPtr.Zero);
}
});
try
{
Console.WriteLine("Interrupting output for user input (10 seconds given)");
string s = Console.ReadLine();
if(s == "stop")
run = false;
else
typing = false;
}
catch(OperationCanceledException)
{
Console.WriteLine("Timeout, press any key to pause again.");
typing = false;
}
}
}