2010-10-30 13 views
8

Sto cercando di capire come funziona ScriptBlock.GetNewClosure(). Sulla base di this filo (vedi risposta di Stej) Ho questo codice:Comportamento ScriptBlock.GetNewClosure()

$i = 1 
$block1 = 
{ 
    $i 
} 

$i = 2 
$block2 = 
{ 
    $i 
} 

$i = 3 
$block3 = 
{ 
    $i 
} 


& $block1 
& $block2 
& $block3 

L'output è:

3 
3 
3 

che si prevede, perché quando vengono eseguite le ScriptBlocks viene utilizzato il valore $ i corrente. Questo può essere modificato con GetNewClosure():

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

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

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


& $block1 
& $block2 
& $block3 

Questa volta l'output è:

1 
2 
3 

Questo è un bene, ma quando provo a stella le ScriptBlocks come posti di lavoro:

$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 

Non c'è uscita. Cercando una risposta, ho trovato il thread this, dove x0n dice che i lavori sono eseguiti in un modulo dinamico. I moduli hanno un sessionstate isolato e condividono l'accesso ai globals. Le chiusure PowerShell funzionano solo all'interno della stessa catena sessione/catena di applicazione

Ciò significa che $ i non è accessibile dai lavori? Quando provo il suo valore:

$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 

$ è uguale a null.

risposta

6

Sì, significa che $i non è accessibile dai lavori in questo modo. Purtroppo. Quindi, utilizzare un altro modo: per esempio, param in un blocco di script per essere invocato come un lavoro e ArgumentList parametro di Start-Job:

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

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

uscita:

84 

P.S. È stato riferito che GetNewClosure anche non funziona con Register-ObjectEvent: https://connect.microsoft.com/PowerShell/feedback/details/541754/getnewclosure-doesnt-work-on-register-objectevent

+0

Grazie per la risposta. Questo comportamento è documentato da Microsoft? –

+0

Beh, direi che è una funzione legale ma la documentazione su di esso potrebbe essere migliore. BTW, invece di 'param' in un blocco di script puoi semplicemente usare' $ args'. –

-1
$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/