multithreading powershell多线程 - Powershell可以并行运行命令吗?




powershell后台执行 powershell后台运行命令 (5)

我有一个powershell脚本来做一些图像批量处理,我想做一些并行处理。 Powershell似乎有一些后台处理选项,如开始工作,等待工作等,但我发现做并行工作的唯一好资源是编写脚本文本并运行这些脚本( PowerShell多线程

理想情况下,我想在.net 4中类似于foreach。

这样的东西看起来很像:

foreach-parallel -threads 4 ($file in (Get-ChildItem $dir))
{
   .. Do Work
}

也许我会更好的下降到C#...


Answers

您可以使用后台作业在Powershell 2中执行并行作业。 查看Start-Job和其他作业cmdlet。

# Loop through the server list
Get-Content "ServerList.txt" | %{

  # Define what each job does
  $ScriptBlock = {
    param($pipelinePassIn) 
    Test-Path "\\$pipelinePassIn\c`$\Something"
    Start-Sleep 60
  }

  # Execute the jobs in parallel
  Start-Job $ScriptBlock -ArgumentList $_
}

Get-Job

# Wait for it all to complete
While (Get-Job -State "Running")
{
  Start-Sleep 10
}

# Getting the information back from the jobs
Get-Job | Receive-Job

Steve Williamssend的回答在理论上是正确的,但在实践中并不如@likwid指出的那样。 我修改后的代码考虑到了工作环境的障碍 -默认情况下不会穿越这个障碍! 自动$_变量因此可以在循环中使用,但不能在脚本块中直接使用,因为它位于由作业创建的单独上下文中。

要将变量从父上下文传递到子上下文,请使用Start-Job上的-ArgumentList参数发送它,并在脚本块内使用param来接收它。

cls
# Send in two root directory names, one that exists and one that does not.
# Should then get a "True" and a "False" result out the end.
"temp", "foo" | %{

  $ScriptBlock = {
    # accept the loop variable across the job-context barrier
    param($name) 
    # Show the loop variable has made it through!
    Write-Host "[processing '$name' inside the job]"
    # Execute a command
    Test-Path "\$name"
    # Just wait for a bit...
    Start-Sleep 5
  }

  # Show the loop variable here is correct
  Write-Host "processing $_..."

  # pass the loop variable across the job-context barrier
  Start-Job $ScriptBlock -ArgumentList $_
}

# Wait for all to complete
While (Get-Job -State "Running") { Start-Sleep 2 }

# Display output from all jobs
Get-Job | Receive-Job

# Cleanup
Remove-Job *

(我通常喜欢提供PowerShell文档作为支持性证据的参考,但是,唉,我的搜索没有结果,如果你碰巧知道在哪里记录了上下文分离,请在这里发表评论以让我知道!)



http://gallery.technet.microsoft.com/scriptcenter/Invoke-Async-Allows-you-to-83b0c9f0

我创建了一个invoke-async,它允许你同时运行多个脚本块/ cmdlet /函数。 这对于小型作业(对100台机器的子网扫描或wmi查询)非常有用,因为创建一个运行空间相对于启动时间的开销非常大。 它可以像这样使用。

与scriptblock,

$sb = [scriptblock] {param($system) gwmi win32_operatingsystem -ComputerName $system | select csname,caption} 

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $server -SetParam system  -ScriptBlock $sb

只是cmdlet /函数

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $servers -SetParam computername -Params @{count=1} -Cmdlet Test-Connection -ThreadCount 50

  • Platform.runLater :如果需要从非GUI线程更新GUI组件,可以使用它来将更新放入队列中,并尽快由GUI线程处理。
  • Task实现了Worker接口,当你需要在GUI线程之外运行一个长任务(以避免冻结你的应用程序)时使用它,但仍然需要在某个阶段与GUI交互。

如果您熟悉Swing,前者相当于SwingUtilities.invokeLater ,后者则相当于SwingWorker的概念。

任务javadoc提供了许多示例,应该阐明如何使用它们。 您还可以参考有关并发的教程





multithreading powershell parallel-processing