diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs
index e76c78d6..fa7d93a9 100644
--- a/PSReadLine/ReadLine.cs
+++ b/PSReadLine/ReadLine.cs
@@ -33,15 +33,11 @@ public partial class PSConsoleReadLine : IPSConsoleReadLineMockableMethods
{
private const int ConsoleExiting = 1;
- private const int CancellationRequested = 2;
-
// *must* be initialized in the static ctor
// because the static member _clipboard depends upon it
// for its own initialization
private static readonly PSConsoleReadLine _singleton;
- private static readonly CancellationToken _defaultCancellationToken = new CancellationTokenSource().Token;
-
// This is used by PowerShellEditorServices (the backend of the PowerShell VSCode extension)
// so that it can call PSReadLine from a delegate and not hit nested pipeline issues.
#pragma warning disable CS0649
@@ -143,17 +139,7 @@ private void ReadOneOrMoreKeys()
}
while (_charMap.KeyAvailable)
{
- ConsoleKeyInfo keyInfo = _charMap.ReadKey();
- if (_cancelReadCancellationToken.IsCancellationRequested)
- {
- // If PSReadLine is running under a host that can cancel it, the
- // cancellation will come at a time when ReadKey is stuck waiting for input.
- // The next key press will be used to force it to return, and so we want to
- // discard this key since we were already canceled.
- continue;
- }
-
- var key = PSKeyInfo.FromConsoleKeyInfo(keyInfo);
+ var key = PSKeyInfo.FromConsoleKeyInfo(_charMap.ReadKey());
_lastNKeys.Enqueue(key);
_queuedKeys.Enqueue(key);
}
@@ -170,10 +156,6 @@ private void ReadKeyThreadProc()
break;
ReadOneOrMoreKeys();
- if (_cancelReadCancellationToken.IsCancellationRequested)
- {
- continue;
- }
// One or more keys were read - let ReadKey know we're done.
_keyReadWaitHandle.Set();
@@ -208,7 +190,6 @@ internal static PSKeyInfo ReadKey()
// - a key is pressed
// - the console is exiting
// - 300ms timeout - to process events if we're idle
- // - ReadLine cancellation is requested externally
handleId = WaitHandle.WaitAny(_singleton._requestKeyWaitHandles, 300);
if (handleId != WaitHandle.WaitTimeout)
{
@@ -292,10 +273,12 @@ internal static PSKeyInfo ReadKey()
throw new OperationCanceledException();
}
- if (handleId == CancellationRequested)
+ if (_singleton._cancelReadCancellationToken.IsCancellationRequested)
{
- // ReadLine was cancelled. Save the current line to be restored next time ReadLine
- // is called, clear the buffer and throw an exception so we can return an empty string.
+ // ReadLine was cancelled. Dequeue the dummy input sent by the host, save the current
+ // line to be restored next time ReadLine is called, clear the buffer and throw an
+ // exception so we can return an empty string.
+ _singleton._queuedKeys.Dequeue();
_singleton.SaveCurrentLine();
_singleton._getNextHistoryIndex = _singleton._history.Count;
_singleton._current = 0;
@@ -331,9 +314,7 @@ private void PrependQueuedKeys(PSKeyInfo key)
/// The complete command line.
public static string ReadLine(Runspace runspace, EngineIntrinsics engineIntrinsics, bool? lastRunStatus)
{
- // Use a default cancellation token instead of CancellationToken.None because the
- // WaitHandle is shared and could be triggered accidently.
- return ReadLine(runspace, engineIntrinsics, _defaultCancellationToken, lastRunStatus);
+ return ReadLine(runspace, engineIntrinsics, CancellationToken.None, lastRunStatus);
}
///
@@ -396,7 +377,6 @@ public static string ReadLine(
}
_singleton._cancelReadCancellationToken = cancellationToken;
- _singleton._requestKeyWaitHandles[2] = cancellationToken.WaitHandle;
return _singleton.InputLoop();
}
catch (OperationCanceledException)
@@ -877,7 +857,7 @@ private void DelayedOneTimeInitialize()
_readKeyWaitHandle = new AutoResetEvent(false);
_keyReadWaitHandle = new AutoResetEvent(false);
_closingWaitHandle = new ManualResetEvent(false);
- _requestKeyWaitHandles = new WaitHandle[] {_keyReadWaitHandle, _closingWaitHandle, null};
+ _requestKeyWaitHandles = new WaitHandle[] {_keyReadWaitHandle, _closingWaitHandle};
_threadProcWaitHandles = new WaitHandle[] {_readKeyWaitHandle, _closingWaitHandle};
// This is for a "being hosted in an alternate appdomain scenario" (the