PowerShell Thread jobs
Start-ThreadJob does what Start-Job does, but in a thread inside the current process instead of a whole new process. It ships with PowerShell 7 and is available for 5.1 from the gallery as the ThreadJob module.
Documentation: Microsoft Learn
Overview
The difference is cost. A background job spawns a process, which takes a fifth of a second and tens of megabytes. A thread job costs a fraction of that. For fifty short tasks that gap decides whether the script finishes in seconds or minutes.
Everything else is the same: Get-Job, Receive-Job, Wait-Job and Remove-Job all work on thread jobs, so you can swap Start-Job for Start-ThreadJob and keep the rest of the script.
The trade-off is isolation. Threads share the process, so one thread crashing the runtime takes the others with it, and shared state needs care. Use -ThrottleLimit to cap how many run at once, because launching two hundred threads against one machine will hurt rather than help.
Rule of thumb: thread jobs for many short tasks, background jobs when you need one task genuinely isolated.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
$targets = 'WEB01' , 'WEB02' , 'SQL01' , 'DC01'
$targets | ForEach-Object {
[pscustomobject]@{
Target = $_
Job = 'Start-ThreadJob'
Cost = 'thread, not process'
} }- Stage 1$targets
Positional values or no named parameters - Stage 2ForEach-Object
Positional values or no named parameters
An example to inspect
Preview the example. Sign in for the full lesson and activities.
$targets = 'WEB01' , 'WEB02' , 'SQL01' , 'DC01'
$targets | ForEach-Object {
[pscustomobject]@{
Target = $_
Job = 'Start-ThreadJob'
Cost = 'thread, not process'
} }What happens
This builds one descriptor per target rather than starting real jobs, since jobs would outlive the command. In practice the body would be $targets | ForEach-Object { Start-ThreadJob -ScriptBlock { param($t) Test-Connection $t } -ArgumentList $_ } followed by Get-Job | Wait-Job | Receive-Job.
Worth remembering
- Threads instead of processes, so startup is far cheaper.
- Built into PowerShell 7; install the ThreadJob module for 5.1.
- The same Get-Job, Receive-Job and Wait-Job cmdlets apply.
- Cap concurrency with -ThrottleLimit.
Primary documentation
Try it
Illustrative output · values vary by environment
Example reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
Builds one job descriptor per target to show the pattern.
Show reference output
Illustrative output · values vary by environment
Target Job Cost ------ --- ---- WEB01 Start-ThreadJob thread, not process WEB02 Start-ThreadJob thread, not process SQL01 Start-ThreadJob thread, not process DC01 Start-ThreadJob thread, not process