gpt4 book ai didi

multithreading - 访问当前 PowerShell 实例

转载 作者:行者123 更新时间:2023-12-01 23:04:48 27 4
gpt4 key购买 nike

我有一个 PowerShell 脚本,我想在其中创建一个后台线程并与我的主线程动态交换数据。这个想法是使用信息流,因为它可以轻松处理各种对象。

通常我会像下面这样将 PowerShell 对象赋予自身:

$Code =
{
Param($Me)
#Here I can use $Me.Streams.Information to exchange data any time,
#for example to feed my thread with more work to do on the fly

$ResultData = [System.Object[]]::new(0)
$WorkCounter = 0
$Finished = $false
while (-not $Finished)
{
while ($Me.Streams.Information.Count -eq $WorkCounter)
{
#Wait for data to be added to the information stream
Sleep -MilliSeconds 10
}

$InputData = $Me.Streams.Information[-1].MessageData
if ($InputData -eq "FINISHED")
{
$Finished = $true
}
else
{
<# Do some stuff with the $InputData #>
$ResultData += $ProgressedInputData

}
$WorkCounter++
}
Write-Information $ResultData
}
$PS = [PowerShell]::Create()
$PS.AddScript($Code) | Out-Null
$PS.AddArgument($PS) | Out-Null #Hand the PS to itself to make the streams accessible inside the thread
$Handle = $PS.BeginInvoke() | Out-Null

for ($i = 0; $i -lt 10; $i++)
{
$PS.Streams.Information.Add([System.Management.Automation.InformationRecord]::new($i, ""))
#I just gave my background thread some stuff to do without the need to instantiate a new one again
#Now this thread can do some work too...
}
$PS.Streams.Information.Add([System.Management.Automation.InformationRecord]::new("FINISHED", ""))
$Handle.AsyncWaitHandle.WaitOne() #Wait for my background thread to finish all its work
$SomeReturnValue = $PS.Streams.Information[-1].MessageData

我的实际问题是:是否有可能访问当前的 PowerShell 实例而无需像我使用 $PS.AddArgument($PS) 那样将其移交?

最佳答案

您不需要滥用 PowerShell.Streams 进行双向通信 - PowerShell 已经有一个在两个运行空间之间桥接 session 状态的工具,即所谓的 session 状态代理!

让我们从稍微重写您的 $code block 开始:

$code = {
while($config['Enabled']){
$inputData = $null
if($queue.TryDequeue([ref]$inputData)) {
#process input data
Write-Information $inputData
}
else {
Start-Sleep -Milliseconds 50
}
}
}

请注意,我使用了两个变量,$config$queue,尽管我实际上并没有参数化或以其他方式定义它们,但我们仍然使用信息流来传达输出(您也可以使用标准输出)。

现在我们只需要创建两个可以绑定(bind)到这些变量的对象。为了线程安全,我们将使用:

  • 用于输入数据的 ConcurrentQueue[psobject]
  • 用于配置数据的线程同步[hashtable]
# Create PowerShell instance like before
$PS = [powershell]::Create()

# Create the thread-safe collections we'll be using to communicate
$queue = [System.Collections.Concurrent.ConcurrentQueue[psobject]]::new()
$config = [hashtable]::Synchronized(@{
Enabled = $true
})

# Now make those variable references available in the runspace where the backgroun code will be running
$ps.Runspace.SessionStateProxy.PSVariable.Set('queue', $queue)
$ps.Runspace.SessionStateProxy.PSVariable.Set('config', $config)

通过交换输入和配置数据的工具,您现在可以调用后台作业并根据通过 $queue 提供的输入观察它的行为(我强烈建议输入以下语句进入交互式提示,稍微玩一下):

# Invoke background code
$asyncHandle = $PS.BeginInvoke()

# Try adding some data to the queue
$queue.TryAdd([pscustomobject]@{ Property = "Value 123"})

# Wait for a bit
Start-Sleep -Milliseconds 100

# Observe that the queue has been emptied by the background code
Write-Host "Queue is empty: $($queue.IsEmpty)"

# Observe that the background code actually processed (and output) the data
$ps.Streams.Information

关于multithreading - 访问当前 PowerShell 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71141243/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com