Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # All this C# is to synthesize a signal that corresponds to when a runspace is
- # ready to be used.
- # see also PowerShell/PowerShell#7034
- Add-Type '
- using System.Management.Automation;
- using System.Management.Automation.Runspaces;
- using System.Threading.Tasks;
- using System.Collections.Concurrent;
- using System.Linq;
- using System;
- namespace ns
- {
- public class RunspaceStateTransition : IEquatable<RunspaceStateTransition>
- {
- public Nullable<RunspaceAvailability> Availability { get; private set; }
- public Nullable<RunspaceState> State { get; private set; }
- public RunspaceStateTransition
- (
- Nullable<RunspaceAvailability> availability,
- Nullable<RunspaceState> state
- )
- {
- Availability = availability;
- State = state;
- }
- public bool Equals(RunspaceStateTransition other)
- {
- if (other==null) return false;
- return Availability == other.Availability &&
- State == other.State;
- }
- }
- public static class OpenRunspaceWaiterTask
- {
- public static Task Create(Runspace runspace)
- {
- var tcs = new TaskCompletionSource<object>();
- System.EventHandler<RunspaceAvailabilityEventArgs> availabilityHandler = null;
- System.EventHandler<RunspaceStateEventArgs> stateHandler = null;
- var log = new ConcurrentQueue<RunspaceStateTransition>();
- availabilityHandler = (s,e) => {
- log.Enqueue( new RunspaceStateTransition(e.RunspaceAvailability,null));
- if ( RunspaceIsOpen(runspace.InitialSessionState,log.ToArray()) )
- {
- runspace.AvailabilityChanged -= availabilityHandler;
- runspace.StateChanged -= stateHandler;
- tcs.SetResult(null);
- }
- };
- stateHandler = (s,e) => {
- log.Enqueue( new RunspaceStateTransition(null,e.RunspaceStateInfo.State));
- if ( RunspaceIsOpen(runspace.InitialSessionState,log.ToArray()) )
- {
- runspace.AvailabilityChanged -= availabilityHandler;
- runspace.StateChanged -= stateHandler;
- tcs.SetResult(null);
- }
- };
- runspace.AvailabilityChanged += availabilityHandler;
- runspace.StateChanged += stateHandler;
- return tcs.Task;
- }
- public static bool RunspaceIsOpen(
- InitialSessionState initialSessionState,
- RunspaceStateTransition[] log
- )
- {
- RunspaceStateTransition[] expected = null;
- if ( initialSessionState == null ||
- initialSessionState.Modules.Count == 0 )
- {
- expected = new[] {
- new RunspaceStateTransition(null,RunspaceState.Opening),
- new RunspaceStateTransition(RunspaceAvailability.Available,null),
- new RunspaceStateTransition(null,RunspaceState.Opened )
- };
- }
- else
- {
- expected = new [] {
- new RunspaceStateTransition(null,RunspaceState.Opening),
- new RunspaceStateTransition(RunspaceAvailability.Available,null),
- new RunspaceStateTransition(null,RunspaceState.Opened ),
- new RunspaceStateTransition(RunspaceAvailability.Busy,null),
- new RunspaceStateTransition(RunspaceAvailability.Available,null)
- };
- }
- return log.SequenceEqual(expected);
- }
- }
- }
- ' -ReferencedAssemblies @(
- 'System.Threading.Tasks'
- 'System.Management.Automation'
- 'System.Collections.Concurrent'
- 'System.Linq'
- )
- # Create a module the invokation of whose scriptblock is slow and CPU-bound.
- $moduleContent = {
- function fibonacci {
- param([int]$n)
- [bigint]$a=0
- [bigint]$b=1
- foreach ($x in 0..$n)
- {
- $a,$b = $b,($a+$b)
- }
- $b
- }
- fibonacci 100000
- }
- $modulePath = "$([System.IO.Path]::GetTempPath())slowLoading.psm1"
- $moduleContent | Set-Content $modulePath
- $p = [System.Environment]::ProcessorCount
- "ProcessorCount: $p"
- $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
- $initialSessionState = [initialsessionstate]::CreateDefault()
- $initialSessionState.ImportPSModule($modulePath)
- $runspace = 1..$p | % { [runspacefactory]::CreateRunspace($initialSessionState) }
- $awaiter = $runspace | % { [ns.OpenRunspaceWaiterTask]::Create($_) }
- "$($stopwatch.ElapsedMilliseconds)ms : OpenAsync()"
- $runspace.OpenAsync()
- "$($stopwatch.ElapsedMilliseconds)ms : WaitAll()"
- [System.Threading.Tasks.Task]::WaitAll($awaiter)
- "$($stopwatch.ElapsedMilliseconds)ms : done"
Add Comment
Please, Sign In to add comment