2016-08-27 6 views
0

私はscirptを持っていますが、それはうまくいきますが、マルチスレッドを使用することで少しスピードアップしたいと思います。問題は、多くのコードを変更することなく、それを行うのはちょっと難しいということです。私は新しい分離された範囲で仕事を避けたいですが、それは不可能であるように見えます。また、開始ジョブは本当に遅いです、実行を開始するには~~150ミリ秒必要です。ジョブを回避する方法はありますか?Powershellが完成したスクリプトにマルチスレッドを追加する

Param(
    [int]$arg1 = 2, [int]$arg2 = 3 
) 
$functionDoSomething = { 
    function doSomething($inp) { 
     return $inp + 10 
    } 
} 

function doSomething($inp) { 
    return $inp + 10 
} 

# time: 1523337 ticks 
Measure-Command { 
    Start-Job -Name Job1 -InitializationScript $functionDoSomething -ScriptBlock { 
     return doSomething ($arg1 + $arg2) 
    } -ArgumentList $arg1, $arg2 
    Wait-Job Job1 
    $var2 = Receive-Job Job1 # result is 10, so arguements aren't passed correctly, trick with @($arg1, arg2) = the same result 
} 

# time: 6867 ticks 
Measure-Command { 
    $var3 = doSomething ($arg1 + $arg2) # result is 15 
} 

答えて

0
# Have no fear - Invoke-Parallel is here. Hoping that I can help steer you in the right direction. Let me show you some pseudo code that can point you in the right direction. 

# You need a list of objects in which you want to perform an operation for 
$listOfComputers = @(
'1' 
'2' 
'3' 
) 

# Pipe your array to Invoke-Parallel which takes care of opening threads depending on the amount of objects piped in. 
# If you want to control the amount of simultaneous threads simply help Invoke-Parallel -ShowWindow to see how 
$results = $listOfComputers | Invoke-Parallel -ScriptBlock { 
function doSomething($inp) 
{ 
    return [int]$inp + 10 
} 
if ($_ -eq '1') { Start-Sleep -Seconds 15; Write-Verbose 'Waited 15s' } # Adding this so you can see that this script block is running in a multi-threaded fashion 
# $_ refers to the values inside of $listOfComputers 
return doSomething ($_) 
} -Verbose 

$results 

<# Notice how 11 comes up last 
12 
13 
11 
#> 
+0

ありがとうございました!しかし、この解決策には1つの問題があります。私のスクリプトはエンタープライズ環境で働いています.PSからではなくexternモジュールを追加するのはちょっとした問題です。また、スクリプトはあるマシン上で動作するように意図されており、新しいスレッドでスクリプトの一部を呼び出すことによってスピードアップします。このソリューションがうまくいくかどうかわかりません。 – PatrykMilewski

+0

これは外部モジュールではありません。それは単にあなたのための仕事を容易にする機能です。なぜホイールを再発明するのですか? Invoke-Parallel.ps1ファイルをダウンロードしてください。独自のスクリプトの開始時にこの関数をロードするだけで、Import-Module 'Invoke-Parallel.ps1'を使用して使用できるようになります。この関数は、Start-Jobとそのすべてのオーバーヘッドをバイパスする.NET System.Management.Automation.Runspacesを使用します。 –

+0

私はそれに試してみましょう:) – PatrykMilewski

0

まず(何が正しく、引数を渡し、関数を倍増)、実行空間とRunSpacePoolに見ていません。ランスペースを作成するときに、デフォルト以外のモジュールがロードされるように指定することができます。詳細はこちらhttp://www.get-blog.com/?p=189を参照してください。

$ScriptBlock = { 
param([string]$forinput) 
    "Do something with $forinput" 

    [PSCusomObject]@{ 
    Line1="Something" 
    Line2="Something done to $forinput" 
    }#end of custom object output 

}#end script block 

#Create Runspace pool, 100 min and max. 
#Example data contained within $item.property 
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(100,100) 
$RunspacePool.Open() 
$Jobs = 
foreach ($item in $VariableContainsListOfInput) 
{ 
    $Job = [powershell]::Create(). 
    AddScript($ScriptBlock). 
    AddArgument($item.property) 
    $Job.RunspacePool = $RunspacePool 

[PSCustomObject]@{ 
    Pipe = $Job 
    Result = $Job.BeginInvoke() 
} 
} 

DO{Start-sleep -seconds 1 
}While($Jobs.Result.IsCompleted -contains $false) 

#Loop through jobs, pipe EndInvoke data from runspace into Export-CSV 
$(ForEach ($Job in $Jobs) 
{ $Job.Pipe.EndInvoke($Job.Result) }) | 
Export-Csv -Path "$FullPath\$file" -NoTypeInformation 
#clean up runspace 
$RunspacePool.Close() 
$RunspacePool.Dispose() 
+0

本当に素晴らしい解決策です、ありがとうございます。しかし、私はAlbertoの答えからのInvoke-Parallelを使用する方がずっと簡単で、同様の結果が得られると考えています(遅くなります)。私はそれを試してみてください、多分複雑にしか見えません:p – PatrykMilewski

+0

あなたは大歓迎です!それは私にとっても複雑でした。重要な部分はスクリプトブロックと 'Export-CSV'に送られる出力である' PSCustomObject'です。ここでのボーナスは別の関数/スクリプトにパイプすることができるオブジェクトです。 PowerShellのパワーはObjectです:) – user4317867

関連する問題