In writing a simple tutorial for this years Progressive .Net I thought I'd use the Console to allow some nice visual feedback with requiring a dependency.
System.Console (at least on dotnet core 2.0) is not as threadsafe as you'd hope, and means that writing any simple cross platform console UI is nearly impossible.
So, I started with a draw method like this:
1 2 3 4 5 6 7 8 9 10
This method just takes a sequence of coordinates and characters to write in them, and then moves the cursor around the console to write your inputs. And it works fine.
Then I wanted a sequence of keys pressed by the user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Again, this works fine. And as long as you take one item from the input stream, do all your drawing and then take the next item everything continues to be good.
But… this story doesn't end here. What I was really after was accepting key presses on one thread, and drawing on another.
First problem: it turns out that calling
Console.ReadKey on one thread, and setting
Console.CursorTop/Left on another causes a deadlock.
A bit of research led to the
Console.KeyAvailable property, and rewriting
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Yeah! Spin loop. That looks totally healthy.
Unfortunately, we now have the issue that because
Console.ReadKey is not actively blocking at the moment the key is pressed, the input key is printed directly to the console. There doesn't appear to be anyway of blocking this.
The real pity about all of this is not that it's just wasted a couple of hours of my life writing a "simple" tutorial (although that's pretty annoying!); it's the fact that with dotnet core being genuinely cross platform, I was hoping to use it to write a few nice console UI based applications. It turns out that apart from the well know performance issues of
System.Console, it doesn't currently appear to be possible at all.