powershell 运行空间:访问全局变量 Yes ,还是 no?

问题描述

我在本地系统上导入了这个模块。当我也在本地系统上使用运行空间运行脚本块时,该模块中的函数可在运行空间脚本块中访问。

这个模块创建全局变量。我测试了这些全局变量是否也可以从运行空间中运行的脚本块访问。它们都由 get-variable -scope global -name 返回 但是当我尝试从脚本块访问这些全局变量时,只有一些通过。

如果所有人都不出现,我可以解决这个问题,或者他们都会出现。但是他们都显示为在场,但只有一些人因为有内容而被抛出。

目标是让这个模块在本地系统和在运行空间中运行的本地系统这两个上下文中工作。

解决方法

简而言之,您想在运行空间中看到的所有内容都应传递到其中。

如果您的值为 ValueType,您应该显式地通过引用传递它们。否则,您应该按原样传递它们(引用类型是默认类型)。

这是我使用 PoshRSJob 模块和自定义 SomeFunction 并行处理有限项目列表的模板:

Function SomeFunction
{
    Param(
       [String]$SampleParam
    )
    return $SampleParam.ToUpper()
}

$JobScript = [scriptblock]{
    $inQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]$args[0]
    $outBag = [System.Collections.Concurrent.ConcurrentBag[string]]$args[1]
    $currentItem = $null
    while($inQueue.TryDequeue([ref] $currentItem) -eq $true)
    {
        try
        {
            # Add result to OutBag
            $result = SomeFunction -SampleParam $currentItem -EA Stop
            $outBag.Add( $result )
        }
        catch
        {
            # Catch error
            Write-Output $_.Exception.ToString()
        }
    }
}

$inData = [System.Collections.Concurrent.ConcurrentQueue[string]]::new(
    [String[]](@(1..10000) | % { return [guid]::NewGuid().ToString() }) # Sample strings in lower case
    )

$resultData = [System.Collections.Concurrent.ConcurrentBag[string]]::new()

# Wait for queue to empty
$i_cur = $inData.Count
$i_max = $i_cur

# Start jobs
$jobs = @(1..20) | % { Start-RSJob -ScriptBlock $JobScript -ArgumentList @($inData,$resultData) -FunctionsToImport @('SomeFunction') }

# Wait queue to empty
while($i_cur -gt 0)
{
    Write-Progress -Activity 'Doing job' -Status "$($i_cur) left of $($i_max)" -PercentComplete (100 - ($i_cur / $i_max * 100)) 
    Start-Sleep -Seconds 3 # Update frequency
    $i_cur = $inData.Count
}

# Wait jobs to complete
$logs = $jobs | % { Wait-RSJob -Job $_ } | % { Receive-RSJob -Job $_  } 
$jobs | % { Remove-RSJob -Job $_ }
$Global:resultData = $resultData
$Global:logs = $logs