问题描述
请考虑此代码:
PS> $ timer = New-Object Timers.Timer
PS> $ timer.Interval = 1000
PS> $ i = 1;
PS> Register-ObjectEvent $ timer Elapsed -Action {write-host'i:'$ i} .GetNewClosure()
PS> $ timer.Enabled = 1
i:1
i:1
i:1
...
#等待几秒钟并更改$ i
PS> ; $ i = 2
i:2
i:2
i:2
我假设当我创建新的闭包( {write-host'i:'$ i} .GetNewClosure()
) / code>将绑定到这个闭包。但不是在这种情况下。 Afer我改变值,
write-host
接受新值。
另一方面,
PS> $ i = 1;
PS> $ action = {write-host'i:'$ i} .GetNewClosure()
PS> & $ action
i:1
PS> $ i = 2
PS> & $ action
i:1
为什么不能使用 Register-ObjectEvent
?
模块具有隔离的会话状态,并且共享对全局的访问。 PowerShell闭包只在同一个会话状态/范围链内工作。恼人,是的。
我说jobs,因为事件处理程序是有效的本地作业,没有不同于使用start-job运行脚本(仅本地计算机,隐式,不使用-computer localhost)
Consider this code:
PS> $timer = New-Object Timers.Timer
PS> $timer.Interval = 1000
PS> $i = 1;
PS> Register-ObjectEvent $timer Elapsed -Action { write-host 'i: ' $i }.GetNewClosure()
PS> $timer.Enabled = 1
i: 1
i: 1
i: 1
...
# wait a couple of seconds and change $i
PS> $i = 2
i: 2
i: 2
i: 2
I assumed that when I create new closure ({ write-host 'i: ' $i }.GetNewClosure()
) value of $i
will be tied to this closure. But not in this case. Afer I change the value, write-host
takes the new value.
On the other side, this works:
PS> $i = 1;
PS> $action = { write-host 'i: ' $i }.GetNewClosure()
PS> &$action
i: 1
PS> $i = 2
PS> &$action
i: 1
Why it doesn't work with the Register-ObjectEvent
?
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. Annoying, yes.
-Oisin
p.s. I say "jobs" because event handlers are effectively local jobs, no different than script being run with start-job (local machine only, implicit, not using -computer localhost)
这篇关于脚本块上的新闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!