How to pass a custom function inside a ForEach-Object -Parallel

点点圈 提交于 2021-02-18 06:26:49

问题


I can't find a way to pass the function. Just variables.

Any ideas without putting the function inside the ForEach loop?

function CustomFunction {
    Param (
        $A
    )
    Write-Host $A
}

$List = "Apple", "Banana", "Grape" 
$List | ForEach-Object -Parallel {
    Write-Host $using:CustomFunction $_
}


回答1:


The solution isn't quite as straightforward as one would hope:

function CustomFunction {
    Param ($A)
    "[$A]"
}

# Get the function's definition *as a string*
$funcDef = $function:CustomFunction.ToString()

"Apple", "Banana", "Grape"  | ForEach-Object -Parallel {
    # Define the function inside this thread...
    $function:CustomFunction = $using:funcDef
    # ... and call it.
    CustomFunction $_
}
  • This approach is necessary, because - aside from the current location (working directory) and environment variables (which apply process-wide) - the threads that ForEach-Object -Parallel creates do not see the caller's state, notably neither with respect to variables nor functions (and also not custom PS drives and imported modules).

  • As of PowerShell 7.0, an enhancement is being discussed on GitHub to support copying the caller's state to the threads on demand, which would make the caller's functions available.

Note that making do without the aux. $funcDef variable and trying to redefine the function with $function:CustomFunction = $using:function:CustomFunction is tempting, but $function:CustomFunction is a script block, and the use of script blocks with the $using: scope specifier is explicitly disallowed.

$function:CustomFunction is an instance of namespace variable notation, which allows you to both get a function (its body as a [scriptblock] instance) and to set (define) it, by assigning either a [scriptblock] or a string containing the function body.




回答2:


I just figured out another way using get-command, which works with the call operator. $a ends up being a FunctionInfo object. EDIT: I'm told this isn't thread safe, but I don't understand why.

function hi { 'hi' }
$a = get-command hi
1..3 | foreach -parallel { & $using:a }

hi
hi
hi


来源:https://stackoverflow.com/questions/61273189/how-to-pass-a-custom-function-inside-a-foreach-object-parallel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!