ScriptBlock.GetNewClosure()行为

9 powershell

我试图找出ScriptBlock.GetNewClosure()的工作原理.基于这个帖子(参见Stej的回答)我有这个代码:

$i = 1
$block1 = 
{
    $i
}

$i = 2
$block2 = 
{
    $i
}

$i = 3
$block3 = 
{
    $i
}


& $block1
& $block2
& $block3
Run Code Online (Sandbox Code Playgroud)

输出是:

3
3
3
Run Code Online (Sandbox Code Playgroud)

这是预期的,因为当执行ScriptBlocks时,使用当前的$ i值.这可以使用GetNewClosure()更改:

$i = 1
$block1 = 
{
    $i
}.GetNewClosure()

$i = 2
$block2 = 
{
    $i
}.GetNewClosure()

$i = 3
$block3 = 
{
    $i
}.GetNewClosure()


& $block1
& $block2
& $block3
Run Code Online (Sandbox Code Playgroud)

这次输出是:

1
2
3
Run Code Online (Sandbox Code Playgroud)

这很好,但是当我尝试将ScriptBlocks作为作业加注时:

$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
Run Code Online (Sandbox Code Playgroud)

没有输出.在寻找答案时,我找到了这个线程,其中x0n表示作业是在动态模块中执行的.模块具有隔离的会话状态,并共享对全局变量的访问.PowerShell闭包只能在同一个sessionstate/scope链中工作

这是否意味着$ i无法从工作中获取?当我测试它的值时:

$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
Run Code Online (Sandbox Code Playgroud)

$等于null.

Rom*_*min 8

是的,这意味着$i以这种方式无法从作业访问.不幸.因此,使用另一种方式:例如,param在作为作业和ArgumentList参数调用的脚本块中Start-Job:

$i = 42
$block1 =
{
    param($i)
    $i * 2
}

$job1 = Start-Job $block1 -ArgumentList $i
$job1 | Wait-Job | Receive-Job
Run Code Online (Sandbox Code Playgroud)

输出:

84
Run Code Online (Sandbox Code Playgroud)

PS据报道,它GetNewClosure也无法使用Register-ObjectEvent:https: //connect.microsoft.com/PowerShell/feedback/details/541754/getnewclosure-doesnt-work-on-register-objectevent