After removing the call to move() between the Console.Write and Console.WriteLine calls, there are 4 calls to TCGETS and none to TCSETS. Are you sure those TCGETS are coming from this code? I don't see anything on our Console.Write paths that would cause a TCGET. The calls to Presumably so do the I'd have expected those to be all of the and So, 2 calls to it means we do 5 calls to Part of the problem is we don't expose a way to get both the "Left" and "Top" at the same time; exposing that would cut the number in half. That's covered by: https://github.com/dotnet/corefx/issues/34885 cc: @wtgodbe so I am not sure if we can reduce the number of syscalls in any way or not. Assuming I'm right about the 2+1 above, I'm not sure there's much we can do unless we rearchitect how we handle all of this. There are two related pieces here that come up not infrequently:
For (1): https://github.com/dotnet/corefx/issues/34501 For (2): https://github.com/dotnet/corefx/issues/31517 I can confirm that Mono doesn't have any issue. Mono tries to cache the current cursor position, such that CursorLeft and CursorTop hand back the cached value. That makes getting the current position super fast, which is awesome, but it can lead to correctness problems if anything that's not being monitored invalidates the cached notion of where it currently is. For example, it doesn't monitor terminal scrolling / resizing with regards to cursor position, so try a program like this: using System; using System.Threading; class Program { }let it output a few lines, and then shrink the window by pushing up the bottom of the terminal such that the terminal is only a few lines tall. It'll continue to still say the position is what it was, because it's pulling it from its cache that wasn't invalidated. That's not casting aspersions at Mono, just highlighting that there are difficulties here. Of course as has been pointed out, Mono's implementation of CursorTop/Left is way faster when compared to the current implementation in corefx, and it's only the corner-cases that break, so it may very well be that it's following the right approach, corefx is in the wrong, and we should pursue this route instead. It comes up enough. We just need to do real due diligence in making sure that we are aggressive about invalidating the cache when anything that could impact it happens; we should be able to do that, though, we just need a lot of eyes on it to make sure nothing slips through the gaps. Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support. Console.CursorTop Property
DefinitionGets or sets the row position of the cursor within the buffer area.
Property ValueThe current position, in rows, of the cursor. Attributes ExceptionsThe value in a set operation is less than zero. -or- The value in a set operation is greater than or equal to . The user does not have permission to perform this action. ExamplesThis example demonstrates the CursorLeft and CursorTop properties, and the SetCursorPosition and Clear methods. The example positions the cursor, which determines where the next write will occur, to draw a 5 character by 5 character rectangle using a combination of "+", "|", and "-" strings. Note that the rectangle could be drawn with fewer steps using a combination of other strings. `// This example demonstrates the // Console.CursorLeft and // Console.CursorTop properties, and the // Console.SetCursorPosition and // Console.Clear methods. using namespace System; int origRow; int origCol; void WriteAt( String^ s, int x, int y ) { try { }
catch ( ArgumentOutOfRangeException^ e )
{ }
}
int main()
{
// Clear the screen, then save the top and left coordinates.
Console::Clear();
origRow = Console::CursorTop;
origCol = Console::CursorLeft;
// Draw the left side of a 5x5 rectangle, from top to bottom.
WriteAt( "+", 0, 0 );
WriteAt( "|", 0, 1 );
WriteAt( "|", 0, 2 );
WriteAt( "|", 0, 3 );
WriteAt( "+", 0, 4 );
// Draw the bottom side, from left to right.
WriteAt( "-", 1, 4 ); // shortcut: WriteAt("-", 1, 4)
WriteAt( "-", 2, 4 ); // ...
WriteAt( "-", 3, 4 ); // ...
WriteAt( "+", 4, 4 );
// Draw the right side, from bottom to top.
WriteAt( "|", 4, 3 );
WriteAt( "|", 4, 2 );
WriteAt( "|", 4, 1 );
WriteAt( "+", 4, 0 );
// Draw the top side, from right to left.
WriteAt( "-", 3, 0 ); // shortcut: WriteAt("-", 1, 0)
WriteAt( "-", 2, 0 ); // ...
WriteAt( "-", 1, 0 ); // ...
//
WriteAt( "All done!", 0, 6 );
Console::WriteLine();
}
/*
This example produces the following results:
+---+All done! */ ` `// This example demonstrates the // Console.CursorLeft and // Console.CursorTop properties, and the // Console.SetCursorPosition and // Console.Clear methods. using System; class Sample { // Clear the screen, then save the top and left coordinates. // Draw the left side of a 5x5 rectangle, from top to bottom. // Draw the bottom side, from left to right. // Draw the right side, from bottom to top. // Draw the top side, from right to left. // }
/*
This example produces the following results:
+---+All done! */ `
0
1 Applies toCollaborate with us on GitHub The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, see our contributor guide. |