2012-10-07 41 views
15

Tôi không chắc liệu có cần gọi đa luồng, dựa trên công việc hay không đồng bộ, nhưng về cơ bản tôi có hàm Powershell cần vài tham số và cần phải gọi nó nhiều lần với các tham số khác nhau và có các lệnh này song song.Làm thế nào để thực hiện chức năng Powershell nhiều lần song song

Hiện nay, tôi gọi hàm như thế này:

Execute "param1" "param2" "param3" "param4" 

Làm thế nào tôi có thể gọi đây là nhiều lần mà không cần chờ đợi cho mỗi cuộc gọi đến Execute trở lại cho người gọi?

Hiện nay tôi đang chạy v2.0 nhưng tôi có thể cập nhật nếu cần thiết

EDIT: đây là những gì tôi có cho đến nay, mà không làm việc:

$cmd = { 
    param($vmxFilePath,$machineName,$username,$password,$scriptTpath,$scriptFile,$uacDismissScript,$snapshotName) 
    Execute $vmxFilePath $machineName $username $password $scriptTpath $scriptFile $uacDismissScript $snapshotName 
} 

Start-Job -ScriptBlock $cmd -ArgumentList $vmxFilePath, $machineName, $username $password, $scriptTpath, $scriptFile, $uacDismissScript, $snapshotName 

tôi nhận được một lỗi:

cannot convert 'system.object[]' to the type 'system.management.automation.scriptblock' required by parameter 'initializationscript'. specified method is not supported 

EDIT2: Tôi đã sửa đổi tập lệnh nhưng vẫn gặp lỗi được đề cập ở trên. Đây là mod của tôi:

$cmd = { 
    param($vmxFilePath,$machineName,$username,$password,$scriptTpath,$scriptFile,$uacDismissScript,$snapshotName) 
    Execute $vmxFilePath $machineName $username $password $scriptTpath $scriptFile $uacDismissScript $snapshotName 
} 

Start-Job -ScriptBlock $cmd -ArgumentList $vmxFilePath, $machineName, $username $password, $scriptTpath, $scriptFile, $uacDismissScript, $snapshotName 

Trả lời

29

Không cần cập nhật cho điều này. Xác định khối tập lệnh và sử dụng Start-Job để chạy khối tập lệnh nhiều lần nếu cần. Ví dụ:

$cmd = { 
    param($a, $b) 
    Write-Host $a $b 
} 

$foo = "foo" 

1..5 | ForEach-Object { 
    Start-Job -ScriptBlock $cmd -ArgumentList $_, $foo 
} 

Khối kịch bản mất 2 thông số $a$b được thông qua tùy chọn -ArgumentList. Trong ví dụ trên, các bài tập là $_$a$foo$b. $foo chỉ là một ví dụ cho một tham số cấu hình nhưng tĩnh.

Chạy Get-Job | Remove-Job tại một số điểm để xóa công việc đã hoàn thành khỏi hàng đợi (hoặc Get-Job | % { Receive-Job $_.Id; Remove-Job $_.Id } nếu bạn muốn truy xuất đầu ra).

+0

Tôi vẫn đang gặp khó khăn lập bản đồ giải pháp của bạn để có được kịch bản của riêng tôi để làm việc. Tôi sẽ bắt đầu đơn giản, và chỉ cố gắng để có được Start-Job chạy scriptblock của tôi với các đối số mà hàm tùy chỉnh của tôi, Execute, yêu cầu. Có lẽ bạn có thể mở rộng? Là $ foo một tham số ngoài các tham số được chỉ định bởi param ($ a, $ b)? – JohnZaj

+0

Tôi thấy bây giờ, cảm ơn. Tôi vẫn nhận được lỗi mặc dù. Nếu bạn không chắc chắn điều này có thể là gì, tôi sẽ chỉ tạo bài đăng/câu hỏi riêng. – JohnZaj

+0

Đối với mục đích thử nghiệm, thay thế cuộc gọi của hàm 'Execute()' bằng mã chỉ lặp lại các tham số. Điều đó có hiệu quả không? Nếu có, vấn đề nằm ở hàm bạn muốn gọi. –

16

Dưới đây là một scriptblock giả nhanh chóng với mục đích thử nghiệm:

$Code = { 
    param ($init) 
    $start = Get-Date 
    (1..30) | % { Start-Sleep -Seconds 1; $init +=1 } 
    $stop = Get-Date 
    Write-Output "Counted from $($init - 30) until $init in $($stop - $start)." 
} 

scriptblock này sau đó có thể được thông qua vào Start-Job, với ví dụ 3 thông số (10, 15, 35)

$jobs = @() 
(10,15,35) | % { $jobs += Start-Job -ArgumentList $_ -ScriptBlock $Code } 

Wait-Job -Job $jobs | Out-Null 
Receive-Job -Job $jobs 

Điều này tạo ra 3 công việc, gán chúng cho biến $jobs, chạy chúng song song và sau đó đợi 3 công việc này kết thúc và lấy kết quả:

Counted from 10 until 40 in 00:00:30.0147167. 
Counted from 15 until 45 in 00:00:30.0057163. 
Counted from 35 until 65 in 00:00:30.0067163. 

này đã không mất 90 giây để thực hiện, chỉ có 30.

Một trong những phần khó khăn là cung cấp -Argumentlist để Start-Job, và bao gồm một param() khối bên trong ScriptBlock. Nếu không, các giá trị của bạn sẽ không bao giờ được thấy bởi tập lệnh.

3

Tôi rất tiếc vì mọi người đã bỏ lỡ sự cố của bạn - Tôi biết đã quá muộn rồi, nhưng ...

Lỗi này là do bạn thiếu dấu phẩy giữa $ username và $ password trong danh sách của mình.

Bạn có thể kiểm tra nó ra với đoạn này, mà tôi mô hình ra các câu trả lời trước:

$cmd = { 
    param($a, $b, $c, $d) 
} 
$foo = "foo" 
$bar = "bar" 
start-job -scriptblock $cmd -ArgumentList "a", $foo, $bar, "gold" #added missing comma for this to work 
2

Bạn có thể sử dụng một sự thay thế có thể được nhanh hơn so với việc gọi nếu chức năng không phải là một chặng đường dài chạy một . Max thread là 25 và tôi chỉ gọi hàm này 10 lần, vì vậy tôi mong đợi tổng thời gian chạy của tôi là 5 giây. Bạn có thể bọc Measure-Command xung quanh câu lệnh 'results =' để xem thống kê.

Ví dụ:

$ScriptBlock = { 
     Param ([int]$RunNumber) 

     Start-Sleep -Seconds 5 
     Return $RunNumber 

    } 



    $runNumbers = @(1..10) 


    $MaxThreads = 25 
    $runspacePool = [RunspaceFactory ]::CreateRunspacePool(1, $MaxThreads) 
    $runspacePool.Open() 


    $pipeLines = foreach($num in $runNumbers){ 

           $pipeline = [powershell]::Create() 
           $pipeline.RunspacePool = $runspacePool 
           $pipeline.AddScript($ScriptBlock) | Out-Null 
           $pipeline.AddArgument($num) | Out-Null 

           $pipeline | Add-Member -MemberType NoteProperty -Name 'AsyncResult' -Value $pipeline.BeginInvoke() -PassThru 
        } 



    #obtain results as they come. 
    $results = foreach($pipeline in $pipeLines){ 
         $pipeline.EndInvoke($pipeline.AsyncResult) 
       } 


    #cleanup code. 
    $pipeLines | % { $_.Dispose()} 
    $pipeLines = $null 
    if ($runspacePool) { $runspacePool.Close()} 

    #your results 
    $results 
Các vấn đề liên quan