@@ -314,31 +314,52 @@ public void SetExit()
314
314
315
315
internal void ForceSetExit ( ) => _shouldExit = true ;
316
316
317
- public Task < T > InvokeTaskOnPipelineThreadAsync < T > (
318
- SynchronousTask < T > task )
317
+ private bool CancelForegroundAndPrepend ( ISynchronousTask task , bool isIdle = false )
319
318
{
320
319
// NOTE: This causes foreground tasks to act like they have `ExecutionPriority.Next`.
321
- // TODO: Deduplicate this.
322
- if ( task . ExecutionOptions . RequiresForeground )
323
- {
324
- // When a task must displace the current foreground command,
325
- // we must:
326
- // - block the consumer thread from mutating the queue
327
- // - cancel any running task on the consumer thread
328
- // - place our task on the front of the queue
329
- // - skip the next prompt so the task runs instead
330
- // - unblock the consumer thread
331
- using ( _taskQueue . BlockConsumers ( ) )
320
+ //
321
+ // When a task must displace the current foreground command,
322
+ // we must:
323
+ // - block the consumer thread from mutating the queue
324
+ // - cancel any running task on the consumer thread
325
+ // - place our task on the front of the queue
326
+ // - skip the next prompt so the task runs instead
327
+ // - unblock the consumer thread
328
+ if ( ! task . ExecutionOptions . RequiresForeground )
329
+ {
330
+ return false ;
331
+ }
332
+
333
+ _skipNextPrompt = true ;
334
+
335
+ if ( task is SynchronousPowerShellTask < PSObject > psTask )
336
+ {
337
+ psTask . MaybeAddToHistory ( ) ;
338
+ }
339
+
340
+ using ( _taskQueue . BlockConsumers ( ) )
341
+ {
342
+ _taskQueue . Prepend ( task ) ;
343
+ if ( isIdle )
344
+ {
345
+ CancelIdleParentTask ( ) ;
346
+ }
347
+ else
332
348
{
333
349
CancelCurrentTask ( ) ;
334
- _taskQueue . Prepend ( task ) ;
335
- _skipNextPrompt = true ;
336
350
}
351
+ }
337
352
353
+ return true ;
354
+ }
355
+
356
+ public Task < T > InvokeTaskOnPipelineThreadAsync < T > ( SynchronousTask < T > task )
357
+ {
358
+ if ( CancelForegroundAndPrepend ( task ) )
359
+ {
338
360
return task . Task ;
339
361
}
340
362
341
- // TODO: Apply stashed `QueueTask` function.
342
363
switch ( task . ExecutionOptions . Priority )
343
364
{
344
365
case ExecutionPriority . Next :
@@ -819,7 +840,7 @@ private void DoOneRepl(CancellationToken cancellationToken)
819
840
{
820
841
UI . WriteLine ( ) ;
821
842
}
822
- // Propogate cancellation if that's what happened, since ReadLine won't.
843
+ // Propagate cancellation if that's what happened, since ReadLine won't.
823
844
// TODO: We may not need to do this at all.
824
845
cancellationToken . ThrowIfCancellationRequested ( ) ;
825
846
return ; // Task wasn't canceled but there was no input.
@@ -1047,15 +1068,8 @@ private void OnPowerShellIdle(CancellationToken idleCancellationToken)
1047
1068
while ( ! cancellationScope . CancellationToken . IsCancellationRequested
1048
1069
&& _taskQueue . TryTake ( out ISynchronousTask task ) )
1049
1070
{
1050
- // NOTE: This causes foreground tasks to act like they have `ExecutionPriority.Next`.
1051
- // TODO: Deduplicate this.
1052
- if ( task . ExecutionOptions . RequiresForeground )
1071
+ if ( CancelForegroundAndPrepend ( task , isIdle : true ) )
1053
1072
{
1054
- // If we have a task that is queued, but cannot be run under readline
1055
- // we place it back at the front of the queue, and cancel the readline task
1056
- _taskQueue . Prepend ( task ) ;
1057
- _skipNextPrompt = true ;
1058
- _cancellationContext . CancelIdleParentTask ( ) ;
1059
1073
return ;
1060
1074
}
1061
1075
@@ -1082,7 +1096,7 @@ private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)
1082
1096
_cancellationContext . CancelCurrentTask ( ) ;
1083
1097
1084
1098
// If the current task was running under the debugger, we need to synchronize the
1085
- // cancelation with our debug context (and likely the debug server). Note that if we're
1099
+ // cancellation with our debug context (and likely the debug server). Note that if we're
1086
1100
// currently stopped in a breakpoint, that means the task is _not_ under the debugger.
1087
1101
if ( ! CurrentRunspace . Runspace . Debugger . InBreakpoint )
1088
1102
{
@@ -1166,7 +1180,7 @@ private void OnDebuggerStopped(object sender, DebuggerStopEventArgs debuggerStop
1166
1180
// selection and terminating the debugger. Without this, if the "Stop" button is pressed
1167
1181
// then we hit this repeatedly.
1168
1182
//
1169
- // This info is publically accessible via `PSDebugContext` but we'd need to access it
1183
+ // This info is publicly accessible via `PSDebugContext` but we'd need to access it
1170
1184
// via a script. At this point in the call I'd prefer this to be as light as possible so
1171
1185
// we can escape ASAP but we may want to consider switching to that at some point.
1172
1186
if ( ! Runspace . RunspaceIsRemote && s_scriptDebuggerTriggerObjectProperty is not null )
0 commit comments