Skip to content

Commit 72edd44

Browse files
Respect cancellation in ReadOneOrMoreKeys() (#3274)
Because .NET's . `Console.ReadKey()` is uncancellable, when a hosting application cancels PSReadLine, it also has to send a key press to get `ReadKey` to return. In this case, we want to ignore the key press (and a user certainly would not be expecting it, as `ReadLine` has already been canceled).
1 parent 38395ad commit 72edd44

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

PSReadLine/ReadLine.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ bool IPSConsoleReadLineMockableMethods.RunspaceIsRemote(Runspace runspace)
9191
return runspace?.ConnectionInfo != null;
9292
}
9393

94-
private void ReadOneOrMoreKeys()
94+
private void ReadOneOrMoreKeys(CancellationToken cancellationToken)
9595
{
9696
_readkeyStopwatch.Restart();
9797
while (_console.KeyAvailable)
@@ -144,6 +144,14 @@ private void ReadOneOrMoreKeys()
144144
while (_charMap.KeyAvailable)
145145
{
146146
var key = PSKeyInfo.FromConsoleKeyInfo(_charMap.ReadKey());
147+
if (cancellationToken.IsCancellationRequested)
148+
{
149+
// If PSReadLine is running under a host that can cancel it, the
150+
// cancellation will come at a time when ReadKey is stuck waiting for input.
151+
// The next key press will be used to force it to return, and so we want to
152+
// discard this key since we were already canceled.
153+
continue;
154+
}
147155
_lastNKeys.Enqueue(key);
148156
_queuedKeys.Enqueue(key);
149157
}
@@ -160,7 +168,7 @@ private void ReadKeyThreadProc()
160168
break;
161169

162170
var localCancellationToken = _singleton._cancelReadCancellationToken;
163-
ReadOneOrMoreKeys();
171+
ReadOneOrMoreKeys(localCancellationToken);
164172
if (localCancellationToken.IsCancellationRequested)
165173
{
166174
continue;

0 commit comments

Comments
 (0)