The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Start process job$job = Start-Job -Name 'Inventory' -ScriptBlock { Get-Process | Select-Object -First 5 }View examples
Pass explicit argumentsStart-Job -ScriptBlock { param($Path) Get-Item ` -LiteralPath $Path } -ArgumentList ` 'C:/Data/report.csv'View examples
Start thread jobStart-ThreadJob -Name 'FastRead' -ScriptBlock { Get-Date ` }View examples
List jobsGet-Job | Select-Object Id, Name, State, HasMoreData, LocationView examples
Inspect child jobs$job.ChildJobs | Select-Object Id, Name, State, Location, HasMoreDataView examples
Wait with timeoutWait-Job -Job $job -Timeout 60View examples
Wait for any jobWait-Job -Job $jobs -Any -Timeout 30View examples
Receive available outputReceive-Job -Job $jobView examples
Read output non-destructivelyReceive-Job -Job $job -KeepView examples
Wait and receiveReceive-Job -Job $job -Wait -AutoRemoveJobView examples
Start remote job$job = Invoke-Command -ComputerName ` 'server01','server02' -ScriptBlock { Get-Date } -AsJob ` -ThrottleLimit 2View examples
Find failed child jobs$job.ChildJobs | Where-Object State -eq 'Failed' | Format-List Location, JobStateInfo, ErrorView examples
Stop a running jobStop-Job -Job $jobView examples
Remove completed jobRemove-Job -Job $jobView examples
Remove finished jobsGet-Job | Where-Object State -in 'Completed','Failed','Stopped' | Remove-JobView examples

PowerShell jobs make work asynchronous; they do not make it persistent, idempotent, or safe. Process jobs isolate execution and serialize their output, thread jobs share the caller's process, and remote jobs depend on session and transport choices. Bound concurrency, pass explicit input, preserve every output stream, impose timeouts, and design cancellation and cleanup before launching work. Jobs run with the privileges and access of their execution context.

Step by step

Detailed examples

01

Choose isolation deliberately and pass immutable inputs

Start-Job uses a child process, so output is serialized and most live object methods are unavailable after return. Thread jobs are faster and return live objects, but an unhandled native crash or process-wide mutation can affect the caller. Neither job type survives its owning PowerShell process by default. Pass approved values through parameters rather than depending on ambient location, variables, credentials, or mapped drives.

Launch an isolated job with explicit input
$path = 'C:/Data/report.csv'
$job = Start-Job -Name 'InspectReport' -ArgumentList $path -ScriptBlock {
  param([string]$LiteralPath)
  Get-Item -LiteralPath $LiteralPath -ErrorAction Stop | Select-Object FullName, Length, LastWriteTimeUtc
}
Back to quick reference ↑
02

Track state by object identity, including child jobs

Job numeric IDs are scoped to the current session; InstanceId is globally unique but still refers to an in-memory repository entry. Aggregate remote jobs contain child jobs whose Location and errors identify individual targets. A Completed state means execution ended, not that business validation succeeded, while HasMoreData indicates buffered stream records remain.

Inspect parent and child state
$job | Select-Object Id, InstanceId, Name, State, HasMoreData, Location
$job.ChildJobs | Select-Object Id, InstanceId, Name, State, HasMoreData, Location
$job | Format-List JobStateInfo, StatusMessage
Back to quick reference ↑
03

Bound every wait and handle incomplete work

Wait-Job blocks only until the selected terminal-state condition or timeout; a timeout returns no completed job for that selection and does not cancel execution. Retain the original job objects, distinguish completed, failed, stopped, disconnected, and still-running states, then apply an explicit retry or cancellation policy. Avoid tight polling loops.

Wait within a budget and classify remaining state
$completed = Wait-Job -Job $job -Timeout 60
if (-not $completed) {
  Write-Warning 'The job exceeded 60 seconds; reviewing before cancellation.'
  $job | Select-Object Id, Name, State, Location
}
$job.ChildJobs | Group-Object State | Select-Object Name, Count
Back to quick reference ↑
04

Receive output once and preserve all diagnostic streams

Receive-Job normally drains available output; -Keep permits rereading at the cost of retaining memory. Output includes stream records in arrival order, and remoting adds provenance properties. Capture results only after deciding how errors, warnings, verbose, information, and progress records will be retained. Never infer success solely from nonempty success output.

Receive results and retain structured failure context
$results = Receive-Job -Job $job -Keep -ErrorVariable jobErrors -WarningVariable jobWarnings
$results | Export-Clixml -LiteralPath './job-results.clixml'
$jobErrors | Format-List FullyQualifiedErrorId, CategoryInfo, TargetObject, Exception
$job.ChildJobs | Select-Object Location, State, HasMoreData
Back to quick reference ↑
05

Throttle remote jobs and preserve target attribution

Invoke-Command -AsJob returns immediately and creates child jobs for each target. ThrottleLimit bounds simultaneous remote operations, not application load after a command starts. Authentication, endpoint configuration, serialization, and disconnected-session behavior still apply. Roll out read-only probes first, then small batches with per-host idempotency and rollback.

Run a bounded read-only remote inventory
$targets = 'server01','server02'
$job = Invoke-Command -ComputerName $targets -ThrottleLimit 2 -AsJob -ScriptBlock {
  [pscustomobject]@{ ComputerName = $env:COMPUTERNAME; Time = Get-Date; PSVersion = $PSVersionTable.PSVersion.ToString() }
}
Wait-Job -Job $job -Timeout 60 | Out-Null
Receive-Job -Job $job -Keep
Back to quick reference ↑
06

Make cancellation and cleanup explicit

Stop-Job requests that execution stop but cannot undo files written, requests sent, or other external side effects. Design job bodies to be idempotent and cancellation-safe. Receive or archive required output before Remove-Job, which deletes the repository object and buffered data. Clean up terminal jobs to prevent memory growth in long-running consoles.

Cancel after review, capture output, then clean up
if ($job.State -eq 'Running') {
  $job | Select-Object Id, Name, State, Location
  Stop-Job -Job $job
  Wait-Job -Job $job -Timeout 15 | Out-Null
}
Receive-Job -Job $job -Keep -ErrorVariable finalErrors | Export-Clixml './final-job-output.clixml'
Remove-Job -Job $job
Back to quick reference ↑

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Microsoftabout_Jobslearn.microsoft.com
  2. MicrosoftStart-Joblearn.microsoft.com
  3. MicrosoftReceive-Joblearn.microsoft.com
  4. MicrosoftStart-ThreadJoblearn.microsoft.com
  5. Microsoftabout_Remote_Jobslearn.microsoft.com

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback