A number of classes in .NET offer Runspace synchronization. This means that an instance of an object can be made accessible from Runspaces that share a common parent.
The most commonly used Runspace-synchronized object is a hashtable. The hashtable is created using the Synchronized static method of the Hashtable type:
$synchronizedHashtable = [Hashtable]::Synchronized(@{
Key = 'Value'
})
The synchronized hashtable can be added to an InitialSessionState object and then used within a script or command that is running in a Runspace. The changes made to the hashtable within the runspace are visible outside:
$variableEntry = [System.Management.Automation.Runspaces.SessionStateVariableEntry]::new(
'synchronizedHashtable',
$synchronizedHashtable,
''
)
$runspace = [RunspaceFactory]::CreateRunspace([InitialSessionState]::CreateDefault2())
$runspace.InitialSessionState.Variables.Add($variableEntry)
$psInstance = [PowerShell]::Create()
$psInstance.Runspace = $runspace
$runspace.Open()
$psInstance.AddScript('$synchronizedHashtable.Add("NewKey", "NewValue")').Invoke()
After the script has completed, the key added by the script will be visible in the parent Runspace, the current PowerShell session.
In addition to the Runspace-synchronized hashtable, an ArrayList might be created in a similar manner, as follows:
[System.Collections.ArrayList]::Synchronized([System.Collections.ArrayList]::new())
.NET also offers classes in the System.Collections.Concurrent namespace, which offers similar cross-Runspace access: https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.
For example, ConcurrentStack might be used as follows:
$stack = [System.Collections.Concurrent.ConcurrentStack[PSObject]]::new()
$stack.Push('Value')
$variableEntry = [System.Management.Automation.Runspaces.SessionStateVariableEntry]::new(
'stack',
$stack,
''
)
$runspace = [RunspaceFactory]::CreateRunspace([InitialSessionState]::CreateDefault2())
$runspace.InitialSessionState.Variables.Add($variableEntry)
$psInstance = [PowerShell]::Create()
$psInstance.Runspace = $runspace
$runspace.Open()
$psInstance.AddScript('
$value = 0
if ($stack.TryPop([Ref]$value)) {
$value
}
').Invoke()
Each of the collection types in the System.Collections.Concurrent namespace offers similar Try methods to access elements.