Start-ThreadJob

建立類似 Start-Job Cmdlet 的背景作業。

Syntax

Start-ThreadJob
     [-ScriptBlock] <ScriptBlock>
     [-Name <String>]
     [-InitializationScript <ScriptBlock>]
     [-InputObject <PSObject>]
     [-ArgumentList <Object[]>]
     [-ThrottleLimit <Int32>]
     [-StreamingHost <PSHost>]
     [<CommonParameters>]
Start-ThreadJob
     [-FilePath] <String>
     [-Name <String>]
     [-InitializationScript <ScriptBlock>]
     [-InputObject <PSObject>]
     [-ArgumentList <Object[]>]
     [-ThrottleLimit <Int32>]
     [-StreamingHost <PSHost>]
     [<CommonParameters>]

Description

Start-ThreadJob 會建立類似 Start-Job Cmdlet 的背景工作。 主要差異在於建立的作業會在本機進程內的個別線程中執行。 根據預設,作業會使用啟動作業之呼叫端的目前工作目錄。

Cmdlet 也支援 ThrottleLimit 參數,以限制一次執行的作業數目。 隨著更多作業的啟動,它們會排入佇列,並等到目前的作業數目低於節流限制為止。

範例

範例 1 - 建立線程限制為 2 的背景作業

Start-ThreadJob -ScriptBlock { 1..100 | % { sleep 1; "Output $_" } } -ThrottleLimit 2
Start-ThreadJob -ScriptBlock { 1..100 | % { sleep 1; "Output $_" } }
Start-ThreadJob -ScriptBlock { 1..100 | % { sleep 1; "Output $_" } }
Get-Job

Id   Name   PSJobTypeName   State        HasMoreData   Location     Command
--   ----   -------------   -----        -----------   --------     -------
1    Job1   ThreadJob       Running      True          PowerShell   1..100 | % { sleep 1;...
2    Job2   ThreadJob       Running      True          PowerShell   1..100 | % { sleep 1;...
3    Job3   ThreadJob       NotStarted   False         PowerShell   1..100 | % { sleep 1;...

範例 2 - 比較 Start-Job 和 Start-ThreadJob 的效能

此範例顯示和Start-ThreadJob之間的差異Start-Job。 作業會 Start-Sleep 執行 Cmdlet 1 秒。 由於作業會以平行方式執行,因此總運行時間約為 1 秒,以及建立作業所需的任何時間。

# start five background jobs each running 1 second
Measure-Command {1..5 | % {Start-Job {Start-Sleep 1}} | Wait-Job} | Select-Object TotalSeconds
Measure-Command {1..5 | % {Start-ThreadJob {Start-Sleep 1}} | Wait-Job} | Select-Object TotalSeconds

TotalSeconds
------------
   5.7665849
   1.5735008

在減去 1 秒的運行時間之後,您可以看到 Start-Job 建立五個作業大約需要 4.8 秒的時間。 Start-ThreadJob 快 8 倍,需要大約 0.6 秒的時間才能建立五個作業。 結果在環境中可能會有所不同,但相對的改進應該相同。

範例 3 - 使用 InputObject 建立作業

在此範例中,腳本區塊會使用 $input 變數從 InputObject 參數接收輸入。 這也可以透過將 物件管線傳送至 Start-ThreadJob來完成。

$j = Start-ThreadJob -InputObject (Get-Process pwsh) -ScriptBlock { $input | Out-String }
$j | Wait-Job | Receive-Job

NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     94   145.80     159.02      18.31   18276   1 pwsh
    101   163.30     222.05      29.00   35928   1 pwsh

$j = Get-Process pwsh | Start-ThreadJob -ScriptBlock { $input | Out-String }
$j | Wait-Job | Receive-Job

NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     94   145.80     159.02      18.31   18276   1 pwsh
    101   163.30     222.05      29.00   35928   1 pwsh

範例 4 - 將作業輸出串流至父主機

使用 StreamingHost 參數,您可以告訴作業將所有主機輸出導向至特定主機。 如果沒有此參數,輸出會移至作業數據流集合,而且在您收到來自作業的輸出之前,不會出現在主機控制台中。

在這裡範例中,目前的主機會使用$Host自動變數傳遞至 Start-ThreadJob

PS> Start-ThreadJob -ScriptBlock { Read-Host 'Say hello'; Write-Warning 'Warning output' } -StreamingHost $Host

Id   Name   PSJobTypeName   State         HasMoreData     Location      Command
--   ----   -------------   -----         -----------     --------      -------
7    Job7   ThreadJob       NotStarted    False           PowerShell    Read-Host 'Say hello'; ...

PS> Say hello: Hello
WARNING: Warning output
PS> Receive-Job -Id 7
Hello
WARNING: Warning output
PS>

請注意,會顯示來自 Read-Host 的提示,而且您可以輸入輸入。 然後,會顯示來自 Write-Warning 的訊息。 Cmdlet 會 Receive-Job 傳回作業的所有輸出。

範例 5 - 同時下載多個檔案

Cmdlet Invoke-WebRequest 一次只能下載一個檔案。 下列範例會使用 Start-ThreadJob 建立多個線程作業,同時下載多個檔案。

$baseUri = 'https://github.com/PowerShell/PowerShell/releases/download'
$files = @(
    @{
        Uri = "$baseUri/v7.3.0-preview.5/PowerShell-7.3.0-preview.5-win-x64.msi"
        OutFile = 'PowerShell-7.3.0-preview.5-win-x64.msi'
    },
    @{
        Uri = "$baseUri/v7.3.0-preview.5/PowerShell-7.3.0-preview.5-win-x64.zip"
        OutFile = 'PowerShell-7.3.0-preview.5-win-x64.zip'
    },
    @{
        Uri = "$baseUri/v7.2.5/PowerShell-7.2.5-win-x64.msi"
        OutFile = 'PowerShell-7.2.5-win-x64.msi'
    },
    @{
        Uri = "$baseUri/v7.2.5/PowerShell-7.2.5-win-x64.zip"
        OutFile = 'PowerShell-7.2.5-win-x64.zip'
    }
)

$jobs = @()

foreach ($file in $files) {
    $jobs += Start-ThreadJob -Name $file.OutFile -ScriptBlock {
        $params = $using:file
        Invoke-WebRequest @params
    }
}

Write-Host "Downloads started..."
Wait-Job -Job $jobs

foreach ($job in $jobs) {
    Receive-Job -Job $job
}

參數

-ArgumentList

針對 FilePath 或 ScriptBlock 參數所指定的腳本,指定自變數或參數值的陣列。

ArgumentList 必須是命令行上的最後一個參數。 參數名稱後面的所有值都會在自變數清單中解譯值。

Type:Object[]
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-FilePath

指定要作為背景作業執行的腳本檔案。 輸入文稿的路徑和檔名。 腳本必須位於本機電腦或本機計算機可以存取的資料夾中。

當您使用此參數時,PowerShell 會將指定腳本檔案的內容轉換成腳本區塊,並以背景工作的形式執行腳本區塊。

Type:String
Position:0
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:False

-InitializationScript

指定在作業啟動之前執行的命令。 以大括弧 ({}) 括住命令,以建立腳本區塊。

使用此參數來準備執行作業的會話。 例如,您可以使用它將函式和模組新增至會話。

Type:ScriptBlock
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-InputObject

指定做為文稿區塊輸入的物件。 它也允許管線輸入。 $input使用文稿區塊中的自動變數來存取輸入物件。

Type:PSObject
Position:Named
Default value:None
Required:False
Accept pipeline input:True
Accept wildcard characters:False

-Name

指定新作業的易記名稱。 您可以使用名稱來識別作業給其他作業 Cmdlet,例如 Stop-Job Cmdlet。

默認易記名稱為 「Job#」,其中 「#」 是每個作業遞增的序號。

Type:String
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-ScriptBlock

指定要在背景作業中執行的命令。 以大括弧 ({}) 括住命令,以建立腳本區塊。 $Input使用自動變數來存取 InputObject 參數的值。 此為必要參數。

Type:ScriptBlock
Position:0
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:False

-StreamingHost

此參數提供安全線程的方式,允許 Write-Host 輸出直接移至傳入 的 PSHost 物件。 如果沒有它, Write-Host 輸出會移至作業資訊數據流集合,而且在作業完成執行之前,不會出現在主機控制台中。

Type:PSHost
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-ThrottleLimit

此參數會限制一次執行的作業數目。 當作業啟動時,它們會排入佇列,並等到線程集區中有線程可供執行作業為止。 預設限制為5個線程。

線程集區大小是PowerShell工作階段的全域。 在一個 呼叫中指定 ThrottleLimit 會設定相同會話中後續呼叫的限制。

Type:Int32
Position:Named
Default value:5
Required:False
Accept pipeline input:False
Accept wildcard characters:False

輸入

PSObject

輸出

ThreadJob.ThreadJob