-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Description
Start-ThreadJob
allows passing a script block by way of a $using:
reference, which is a convenient way to make a function from the caller's scope available to the job:
PS> function foo { 'bar' }; Start-ThreadJob { & $using:function:foo } | Receive-Job -Wait -AutoRemoveJob
bar
That is, the foo
function's script block ([scriptblock]
instance containing the function body) reported by $function:foo
(namespace variable notation) was referenced via $using:
, allowing it to be called with &
.
Unexpectedly, ForEach-Object -Parallel
, whose behavior is generally very similar to Start-ThreadJob
, explicitly disallows referencing [scriptblock]
-typed values from the caller's scope via $using:
Note:
-
The error message (see below) mentions "undefined behavior" - but wouldn't that apply to
Start-ThreadJob
as well? Is the answer to disallow script blocks in both?- If the concern is thread safety: that problem exists for all reference types passed via
$using:
, not just for script blocks that may form closures with outside values from the caller's scope.
- If the concern is thread safety: that problem exists for all reference types passed via
-
Provide option in ForEach-Object -parallel to transfer current runspace state #12240 proposes an opt-in mechanism for
ForEach-Object -Parallel
to allow copying the calling runspace's state to the parallel threads, which would allow for direct use of function from the caller's scope; however, a lower-overhead way of being able to call functions selectively still seems beneficial. -
Loosely related: Consider deserializing serialized script blocks as such (remoting, background jobs) #11698
Steps to reproduce
function foo { 'bar' }; ForEach-Object -Parallel { & $using:function:foo } | Should -Be 'bar'
Expected behavior
The test should succeed.
Actual behavior
The test fails, because a statement-terminating error occurs:
A ForEach-Object -Parallel using variable cannot be a script block.
Passed-in script block variables are not supported with ForEach-Object -Parallel,
and can result in undefined behavior.
Environment data
PowerShell Core 7.1.0-preview.1