ScriptBlock.GetNewClosure () Поведение - PullRequest
8 голосов
/ 30 октября 2010

Я пытаюсь выяснить, как работает ScriptBlock.GetNewClosure (). На основе этой темы (см. Ответ Stej) у меня есть этот код:

$i = 1
$block1 = 
{
    $i
}

$i = 2
$block2 = 
{
    $i
}

$i = 3
$block3 = 
{
    $i
}


& $block1
& $block2
& $block3

Вывод:

3
3
3

, что ожидается, поскольку при выполнении ScriptBlocks используется текущее значение $ i. Это можно изменить с помощью GetNewClosure ():

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

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

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


& $block1
& $block2
& $block3

На этот раз вывод:

1
2
3

Это хорошо, но когда я пытаюсь пометить 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

Нет вывода. В поисках ответа я нашел этот поток , где x0n говорит, что задания выполняются в динамическом модуле. Модули имеют изолированное состояние сеанса и имеют общий доступ к глобальным объектам. Закрытия PowerShell работают только в одной и той же цепочке состояния сеанса / области действия

Значит ли это, что $ 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

$ равно нулю.

Ответы [ 2 ]

7 голосов
/ 30 октября 2010

Да, это означает, что $i не доступен таким образом. К несчастью. Поэтому используйте другой способ: например, param в блоке сценария, который будет вызван как задание, и ArgumentList параметр Start-Job:

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

$job1 = Start-Job $block1 -ArgumentList $i
$job1 | Wait-Job | Receive-Job

Выход:

84

P.S. Сообщается, что GetNewClosure также не работает с Register-ObjectEvent: https://connect.microsoft.com/PowerShell/feedback/details/541754/getnewclosure-doesnt-work-on-register-objectevent

0 голосов
/ 05 декабря 2015
$i = 1
$block1 =  {"block 1 is $using:i" }.GetNewClosure()

$i = 2
$block2 = { "block 2 is $using:i" }.GetNewClosure()

$job1 = Start-Job $block1
$job1 | Wait-Job 
$job1 | Receive-Job

$job2 = Start-Job $block2
$job2 | Wait-Job 
$job2 | Receive-Job

http://www.powertheshell.com/closure/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...