【问题标题】:powershell how to implement worker threadspowershell如何实现工作线程
【发布时间】:2013-12-09 08:54:57
【问题描述】:

我的脚本有一点性能问题,所以我想实现某种工作线程。但到目前为止我还没有找到解决方案..

我希望是这样的:

  • 启动工作线程池 - 这些线程从队列中获取“命令”并进行处理
  • 主脚本将在运行时将“命令”写入队列
  • 一旦完成,主线程将告诉每个线程停止
  • main 将等待所有工作人员结束后再退出。

有人知道怎么做吗?

【问题讨论】:

  • 到目前为止你尝试过什么?您是否调查过后台作业或运行空间池?
  • 是的,我从 start-job 开始,但到目前为止还没有任何运气从主线程与作业进行通信。运行空间;我看过一些例子,但它似乎非常复杂,与事件相同.. 我需要能够每半小时处理 100.000 个事件 ~ 每秒 95 个事件

标签: multithreading powershell subprocess


【解决方案1】:

您可以使用 Powershell 工作流程来做到这一点。

来自Windows PowerShell: What is Windows PowerShell Workflow?

如果您愿意,工作流也可以并行执行。为了 例如,如果您有一组可以按任意顺序运行的任务,没有 相互依赖,那么你可以让它们或多或少地运行 同一时间

只需搜索“Powershell 工作流程”,您就会找到大量文档来帮助您入门。

【讨论】:

  • 这可能是一种可能性,需要进一步调查。
【解决方案2】:

使用作业的基本方法是这样的:

$task1 = { ls c:\windows\system32 -r *.dll -ea 0 | where LastWriteTime -gt (Get-Date).AddDays(-21) }
$task2 = { ls E:\Symbols -r *.dll | where LastWriteTime -gt (Get-Date).AddDays(-21) }
$task3 = { Invoke-WebRequest -Uri http://blogs.msdn.com/b/mainfeed.aspx?Type=BlogsOnly | % Content }

$job1 = Start-Job $task1; $job2 = Start-Job $task2; $job3 = Start-Job $task3
Wait-Job $job1,$job2,$job3

$job1Data = Receive-Job $job1
$job2Data = Receive-Job $job2
$job3Data = Receive-Job $job3

如果您需要让这些后台作业在循环中等待以按照主脚本的指示进行工作,请查看 this SO answer 以了解如何使用 MSMQ 来执行此操作。

【讨论】:

  • 是的,我知道 start-job.. 经常使用它——但到目前为止,一旦任务启动,我就无法与它进行通信——这正是我所需要的。
  • 您是否点击了答案中的链接 - 它确切地描述了如何做到这一点?
  • 是的,但是由于需要执行的服务器,我无法使用消息队列服务。
  • 但也许这增加了其他可能性,我需要进一步调查。
  • 您的选择在我看来是有限的:作业、运行空间、工作流。作业和工作流都运行“进程外”,因此需要某种形式的 IPC。运行空间池可能是您最好的选择,因为它们在进程内运行,因此您应该能够使用 .NET 队列 (BlockingCollection) 将数据传递给工作脚本。
【解决方案3】:

在 Keith hill 的指导下,我得到了一些帮助 - 我得到了它的工作 - 非常感谢......

这里是我的概念证明的代码片段:

function New-Task([int]$Index,[scriptblock]$ScriptBlock) {
    $ps = [Management.Automation.PowerShell]::Create()
    $res = New-Object PSObject -Property @{
        Index = $Index
        Powershell = $ps
        StartTime = Get-Date
        Busy = $true
        Data = $null
        async = $null
    }

    [Void] $ps.AddScript($ScriptBlock)
    [Void] $ps.AddParameter("TaskInfo",$Res)
    $res.async = $ps.BeginInvoke()
    $res
}

$ScriptBlock = {
    param([Object]$TaskInfo) 
    $TaskInfo.Busy = $false
    Start-Sleep -Seconds 1
    $TaskInfo.Data = "test $($TaskInfo.Data)"
}

$a = New-Task -Index 1 -ScriptBlock $ScriptBlock 
$a.Data = "i was here"
Start-Sleep -Seconds 5
$a

这是证明数据被传递到线程并再次返回的结果:

Data       : test i was here
Busy       : False
Powershell : System.Management.Automation.PowerShell
Index      : 1
StartTime  : 11/25/2013 7:37:07 AM
async      : System.Management.Automation.PowerShellAsyncResult

如您所见,$a.data 现在前面有“test”

非常感谢...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    相关资源
    最近更新 更多