I am trying to figure out how ScriptBlock.GetNewClosure() works. Based on this thread (see Stej's answer) I have this code:
$i = 1
$block1 =
{
$i
}
$i = 2
$block2 =
{
$i
}
$i = 3
$block3 =
{
$i
}
& $block1
& $block2
& $block3
The output is:
3
3
3
which is expected, because when the ScriptBlocks are executed the current $i value is used. This can be changed using GetNewClosure():
$i = 1
$block1 =
{
$i
}.GetNewClosure()
$i = 2
$block2 =
{
$i
}.GetNewClosure()
$i = 3
$block3 =
{
$i
}.GetNewClosure()
& $block1
& $block2
& $block3
This time the output is:
1
2
3
This is good, but when I try to star the ScriptBlocks as jobs:
$i = 1
$block1 =
{
$i
}.GetNewClosure()
$i = 2
$block2 =
{
$i
}.GetNewClosure()
$i = 3
$block3 =
{
$i
}.GetNewClosure()
$job1 = Start-Job $block1
$job1 | Wait-Job
$job1 | Receive-Job
$job2 = Start-Job $block2
$job2 | Wait-Job
$job2 | Receive-Job
$job3 = Start-Job $block3
$job3 | Wait-Job
$job3 | Receive-Job
There is no output. Searching for an answer, I found this thread, where x0n says that jobs are executed in a dynamic module. Modules have isolated sessionstate, and share access to globals. PowerShell closures only work within the same sessionstate / scope chain
Does this mean that $i is not accessible from jobs? When I test its value:
$i = 1
$block1 =
{
$i -eq $null
}.GetNewClosure()
$i = 2
$block2 =
{
$i -eq $null
}.GetNewClosure()
$i = 3
$block3 =
{
$i -eq $null
}.GetNewClosure()
$job1 = Start-Job $block1
$job1 | Wait-Job
$job1 | Receive-Job
$job2 = Start-Job $block2
$job2 | Wait-Job
$job2 | Receive-Job
$job3 = Start-Job $block3
$job3 | Wait-Job
$job3 | Receive-Job
$ is equal to null.