Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fa3413a

Browse files
authored
Merge pull request #1581 from rjmholt/pt-eventing
Implement OnIdle engine events
2 parents 79a586b + 08df557 commit fa3413a

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

‎src/PowerShellEditorServices/Services/PowerShell/Execution/BlockingConcurrentDeque.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public BlockingConcurrentDeque()
3939
};
4040
}
4141

42-
public intCount => _queues[0].Count +_queues[1].Count;
42+
public boolIsEmpty => _queues[0].Count ==0&&_queues[1].Count==0;
4343

4444
public void Prepend(T item)
4545
{

‎src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs‎

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRuns
5757

5858
private readonly IdempotentLatch _isRunningLatch = new();
5959

60+
private EngineIntrinsics _mainRunspaceEngineIntrinsics;
61+
6062
private bool _shouldExit = false;
6163

6264
private string _localComputerName;
@@ -347,17 +349,18 @@ public Task SetInitialWorkingDirectoryAsync(string path, CancellationToken cance
347349

348350
private void Run()
349351
{
350-
(PowerShell pwsh, RunspaceInfo localRunspaceInfo) = CreateInitialPowerShellSession();
352+
(PowerShell pwsh, RunspaceInfo localRunspaceInfo, EngineIntrinsics engineIntrinsics) = CreateInitialPowerShellSession();
353+
_mainRunspaceEngineIntrinsics = engineIntrinsics;
351354
_localComputerName = localRunspaceInfo.SessionDetails.ComputerName;
352355
_runspaceStack.Push(new RunspaceFrame(pwsh.Runspace, localRunspaceInfo));
353356
PushPowerShellAndRunLoop(pwsh, PowerShellFrameType.Normal, localRunspaceInfo);
354357
}
355358

356-
private (PowerShell, RunspaceInfo) CreateInitialPowerShellSession()
359+
private (PowerShell, RunspaceInfo,EngineIntrinsics) CreateInitialPowerShellSession()
357360
{
358-
PowerShell pwsh = CreateInitialPowerShell(_hostInfo, _readLineProvider);
361+
(PowerShell pwsh,EngineIntrinsicsengineIntrinsics) = CreateInitialPowerShell(_hostInfo, _readLineProvider);
359362
RunspaceInfo localRunspaceInfo = RunspaceInfo.CreateFromLocalPowerShell(_logger, pwsh);
360-
return (pwsh, localRunspaceInfo);
363+
return (pwsh, localRunspaceInfo,engineIntrinsics);
361364
}
362365

363366
private void PushPowerShellAndRunLoop(PowerShell pwsh, PowerShellFrameType frameType, RunspaceInfo newRunspaceInfo = null)
@@ -613,7 +616,7 @@ private static PowerShell CreatePowerShellForRunspace(Runspace runspace)
613616
return pwsh;
614617
}
615618

616-
public PowerShell CreateInitialPowerShell(
619+
public (PowerShell,EngineIntrinsics) CreateInitialPowerShell(
617620
HostStartupInfo hostStartupInfo,
618621
ReadLineProvider readLineProvider)
619622
{
@@ -649,7 +652,7 @@ public PowerShell CreateInitialPowerShell(
649652
}
650653
}
651654

652-
return pwsh;
655+
return (pwsh,engineIntrinsics);
653656
}
654657

655658
private Runspace CreateInitialRunspace(InitialSessionState initialSessionState)
@@ -668,7 +671,27 @@ private Runspace CreateInitialRunspace(InitialSessionState initialSessionState)
668671

669672
private void OnPowerShellIdle()
670673
{
671-
if (_taskQueue.Count == 0)
674+
IReadOnlyList<PSEventSubscriber> eventSubscribers = _mainRunspaceEngineIntrinsics.Events.Subscribers;
675+
676+
// Go through pending event subscribers and:
677+
// - if we have any subscribers, ensure we process any events
678+
// - if we have any idle events, generate an idle event and process that
679+
bool runPipelineForEventProcessing = false;
680+
foreach (PSEventSubscriber subscriber in eventSubscribers)
681+
{
682+
runPipelineForEventProcessing = true;
683+
684+
if (string.Equals(subscriber.SourceIdentifier, PSEngineEvent.OnIdle, StringComparison.OrdinalIgnoreCase))
685+
{
686+
// We control the pipeline thread, so it's not possible for PowerShell to generate events while we're here.
687+
// But we know we're sitting waiting for the prompt, so we generate the idle event ourselves
688+
// and that will flush idle event subscribers in PowerShell so we can service them
689+
_mainRunspaceEngineIntrinsics.Events.GenerateEvent(PSEngineEvent.OnIdle, sender: null, args: null, extraData: null);
690+
break;
691+
}
692+
}
693+
694+
if (!runPipelineForEventProcessing && _taskQueue.IsEmpty)
672695
{
673696
return;
674697
}
@@ -688,9 +711,21 @@ private void OnPowerShellIdle()
688711
return;
689712
}
690713

714+
// If we're executing a task, we don't need to run an extra pipeline later for events
715+
// TODO: This may not be a PowerShell task, so ideally we can differentiate that here.
716+
// For now it's mostly true and an easy assumption to make.
717+
runPipelineForEventProcessing = false;
691718
task.ExecuteSynchronously(cancellationScope.CancellationToken);
692719
}
693720
}
721+
722+
// We didn't end up executing anything in the background,
723+
// so we need to run a small artificial pipeline instead
724+
// to force event processing
725+
if (runPipelineForEventProcessing)
726+
{
727+
InvokePSCommand(new PSCommand().AddScript("0", useLocalScope: true), PowerShellExecutionOptions.Default, CancellationToken.None);
728+
}
694729
}
695730

696731
private void OnCancelKeyPress(object sender, ConsoleCancelEventArgs args)
@@ -771,7 +806,8 @@ private Task PopOrReinitializeRunspaceAsync()
771806
// If our main runspace was corrupted,
772807
// we must re-initialize our state.
773808
// TODO: Use runspace.ResetRunspaceState() here instead
774-
(PowerShell pwsh, RunspaceInfo runspaceInfo) = CreateInitialPowerShellSession();
809+
(PowerShell pwsh, RunspaceInfo runspaceInfo, EngineIntrinsics engineIntrinsics) = CreateInitialPowerShellSession();
810+
_mainRunspaceEngineIntrinsics = engineIntrinsics;
775811
PushPowerShell(new PowerShellContextFrame(pwsh, runspaceInfo, PowerShellFrameType.Normal));
776812

777813
_logger.LogError($"Top level runspace entered state '{oldRunspaceState.State}' for reason '{oldRunspaceState.Reason}' and was reinitialized."

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /