en-US/PSParallelPipeline-help.xml

<?xml version="1.0" encoding="utf-8"?>
<helpItems schema="maml" xmlns="http://msh">
  <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10" xmlns:MSHelp="http://msdn.microsoft.com/mshelp">
    <command:details>
      <command:name>Invoke-Parallel</command:name>
      <command:verb>Invoke</command:verb>
      <command:noun>Parallel</command:noun>
      <maml:description>
        <maml:para>Executes parallel processing of pipeline input objects using multithreading.</maml:para>
      </maml:description>
    </command:details>
    <maml:description>
      <maml:para>The `Invoke-Parallel` cmdlet enables parallel processing of input objects in PowerShell, including Windows PowerShell 5.1 , offering functionality similar to `ForEach-Object -Parallel` introduced in PowerShell 7.0. It processes pipeline input across multiple threads, improving performance for tasks that benefit from parallel execution.</maml:para>
    </maml:description>
    <command:syntax>
      <command:syntaxItem>
        <maml:name>Invoke-Parallel</maml:name>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="0" aliases="none">
          <maml:name>ScriptBlock</maml:name>
          <maml:description>
            <maml:para>Defines the script block executed for each input object in parallel.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">ScriptBlock</command:parameterValue>
          <dev:type>
            <maml:name>ScriptBlock</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="funcs">
          <maml:name>Functions</maml:name>
          <maml:description>
            <maml:para>Specifies an array of function names from the local session to include in the runspaces' Initial Session State (https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.initialsessionstate). This enables their use within the parallel script block.</maml:para>
            <maml:para>&gt; [!TIP] &gt; &gt; This parameter is the recommended way to make local functions available in the parallel scope. Alternatively, you can retrieve the function definition as a string (e.g., `$def = ${function:Greet}.ToString()`) and use `$using:` to pass it into the script block, defining it there (e.g., `${function:Greet} = $using:def`).</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">String[]</command:parameterValue>
          <dev:type>
            <maml:name>String[]</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="none">
          <maml:name>InputObject</maml:name>
          <maml:description>
            <maml:para>Specifies the objects to process in the script block. This parameter accepts pipeline input.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">Object</command:parameterValue>
          <dev:type>
            <maml:name>Object</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="tl">
          <maml:name>ThrottleLimit</maml:name>
          <maml:description>
            <maml:para>Sets the maximum number of script blocks executed in parallel across multiple threads. Additional input objects wait until the number of running script blocks falls below this limit.</maml:para>
            <maml:para>&gt; [!NOTE] &gt; &gt; The default value is `5`.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">Int32</command:parameterValue>
          <dev:type>
            <maml:name>Int32</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>5</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="to">
          <maml:name>TimeoutSeconds</maml:name>
          <maml:description>
            <maml:para>Specifies the maximum time (in seconds) to process all input objects. When the timeout is reached, running script blocks are terminated, and remaining input is discarded.</maml:para>
            <maml:para>&gt; [!NOTE] &gt; &gt; A value of `0` (default) disables the timeout, allowing processing to continue until completion.</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">Int32</command:parameterValue>
          <dev:type>
            <maml:name>Int32</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>0</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="unr">
          <maml:name>UseNewRunspace</maml:name>
          <maml:description>
            <maml:para>Uses a new runspace for each parallel invocation instead of reusing existing runspaces in the runspace pool.</maml:para>
          </maml:description>
          <dev:type>
            <maml:name>SwitchParameter</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>False</dev:defaultValue>
        </command:parameter>
        <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="vars">
          <maml:name>Variables</maml:name>
          <maml:description>
            <maml:para>Provides a hashtable of variables to make available in the parallel scope. Keys define the variable names within the script block.</maml:para>
            <maml:para>&gt; [!TIP] &gt; &gt; Use this parameter as an alternative to the `$using:` scope modifier (https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7.4#scope-modifiers).</maml:para>
          </maml:description>
          <command:parameterValue required="true" variableLength="false">Hashtable</command:parameterValue>
          <dev:type>
            <maml:name>Hashtable</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>None</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
    </command:syntax>
    <command:parameters>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="funcs">
        <maml:name>Functions</maml:name>
        <maml:description>
          <maml:para>Specifies an array of function names from the local session to include in the runspaces' Initial Session State (https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.initialsessionstate). This enables their use within the parallel script block.</maml:para>
          <maml:para>&gt; [!TIP] &gt; &gt; This parameter is the recommended way to make local functions available in the parallel scope. Alternatively, you can retrieve the function definition as a string (e.g., `$def = ${function:Greet}.ToString()`) and use `$using:` to pass it into the script block, defining it there (e.g., `${function:Greet} = $using:def`).</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">String[]</command:parameterValue>
        <dev:type>
          <maml:name>String[]</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByValue)" position="named" aliases="none">
        <maml:name>InputObject</maml:name>
        <maml:description>
          <maml:para>Specifies the objects to process in the script block. This parameter accepts pipeline input.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">Object</command:parameterValue>
        <dev:type>
          <maml:name>Object</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="False" position="0" aliases="none">
        <maml:name>ScriptBlock</maml:name>
        <maml:description>
          <maml:para>Defines the script block executed for each input object in parallel.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">ScriptBlock</command:parameterValue>
        <dev:type>
          <maml:name>ScriptBlock</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="tl">
        <maml:name>ThrottleLimit</maml:name>
        <maml:description>
          <maml:para>Sets the maximum number of script blocks executed in parallel across multiple threads. Additional input objects wait until the number of running script blocks falls below this limit.</maml:para>
          <maml:para>&gt; [!NOTE] &gt; &gt; The default value is `5`.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">Int32</command:parameterValue>
        <dev:type>
          <maml:name>Int32</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>5</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="to">
        <maml:name>TimeoutSeconds</maml:name>
        <maml:description>
          <maml:para>Specifies the maximum time (in seconds) to process all input objects. When the timeout is reached, running script blocks are terminated, and remaining input is discarded.</maml:para>
          <maml:para>&gt; [!NOTE] &gt; &gt; A value of `0` (default) disables the timeout, allowing processing to continue until completion.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">Int32</command:parameterValue>
        <dev:type>
          <maml:name>Int32</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>0</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="unr">
        <maml:name>UseNewRunspace</maml:name>
        <maml:description>
          <maml:para>Uses a new runspace for each parallel invocation instead of reusing existing runspaces in the runspace pool.</maml:para>
        </maml:description>
        <command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
        <dev:type>
          <maml:name>SwitchParameter</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>False</dev:defaultValue>
      </command:parameter>
      <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="vars">
        <maml:name>Variables</maml:name>
        <maml:description>
          <maml:para>Provides a hashtable of variables to make available in the parallel scope. Keys define the variable names within the script block.</maml:para>
          <maml:para>&gt; [!TIP] &gt; &gt; Use this parameter as an alternative to the `$using:` scope modifier (https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7.4#scope-modifiers).</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="false">Hashtable</command:parameterValue>
        <dev:type>
          <maml:name>Hashtable</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>None</dev:defaultValue>
      </command:parameter>
    </command:parameters>
    <command:inputTypes>
      <command:inputType>
        <dev:type>
          <maml:name>System.Object</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>You can pipe any object to this cmdlet.</maml:para>
        </maml:description>
      </command:inputType>
    </command:inputTypes>
    <command:returnValues>
      <command:returnValue>
        <dev:type>
          <maml:name>System.Object</maml:name>
        </dev:type>
        <maml:description>
          <maml:para>Returns objects produced by the script block.</maml:para>
        </maml:description>
      </command:returnValue>
    </command:returnValues>
    <maml:alertSet>
      <maml:alert>
        <maml:para>- `Invoke-Parallel` uses multithreading, which may introduce overhead. For small datasets, sequential processing might be faster.</maml:para>
        <maml:para>- Ensure variables or collections passed to the parallel scope are thread-safe (e.g., `[System.Collections.Concurrent.ConcurrentDictionary]`), as shown in Examples 3 and 4.</maml:para>
        <maml:para>- By default, runspaces are reused from a pool to optimize resource usage. Using `-UseNewRunspace` increases memory and startup time but ensures isolation.</maml:para>
      </maml:alert>
    </maml:alertSet>
    <command:examples>
      <command:example>
        <maml:title>------- Example 1: Run a slow script in parallel batches -------</maml:title>
        <dev:code>$message = 'Hello world from '
 
0..10 | Invoke-Parallel {
    $using:message + [runspace]::DefaultRunspace.InstanceId
    Start-Sleep 3
}</dev:code>
        <dev:remarks>
          <maml:para>This example demonstrates parallel execution of a script block with a 3-second delay, appending a unique runspace ID to a message. The `$using:` scope modifier (https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7.4#the-using-scope-modifier)is used to pass the local variable `$message` into the parallel scope, a supported method for accessing external variables in `Invoke-Parallel`.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>-------- Example 2: Demonstrates `-Variables` Parameter --------</maml:title>
        <dev:code>$message = 'Hello world from '
 
0..10 | Invoke-Parallel {
    $message + [runspace]::DefaultRunspace.InstanceId
    Start-Sleep 3
} -Variables @{ message = $message }</dev:code>
        <dev:remarks>
          <maml:para>This example demonstrates the `-Variables` parameter (#-variables), which passes the local variable `$message` into the parallel scope using a hashtable. The key `message` in the hashtable defines the variable name available within the script block, serving as an alternative to the `$using:` scope modifier.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>- Example 3: Adding to a thread-safe collection with `$using:` -</maml:title>
        <dev:code>$dict = [System.Collections.Concurrent.ConcurrentDictionary[int, object]]::new()
Get-Process | Invoke-Parallel { ($using:dict)[$_.Id] = $_ }
$dict[$PID]</dev:code>
        <dev:remarks>
          <maml:para>This example uses a thread-safe dictionary to store process objects by ID, leveraging the `$using:` modifier for variable access.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>Example 4: Adding to a thread-safe collection with `-Variables`</maml:title>
        <dev:code>$dict = [System.Collections.Concurrent.ConcurrentDictionary[int, object]]::new()
Get-Process | Invoke-Parallel { $dict[$_.Id] = $_ } -Variables @{ dict = $dict }
$dict[$PID]</dev:code>
        <dev:remarks>
          <maml:para>Similar to Example 3, this demonstrates the same functionality using `-Variables` instead of `$using:`.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>--------- Example 5: Using the `-Functions` parameter ---------</maml:title>
        <dev:code>function Greet { param($s) "$s hey there!" }
 
0..10 | Invoke-Parallel { Greet $_ } -Functions Greet</dev:code>
        <dev:remarks>
          <maml:para>This example imports a local function `Greet` into the parallel scope using `-Functions` parameter (#-functions), allowing its use within the script block.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>----- Example 6: Setting a timeout with `-TimeoutSeconds` -----</maml:title>
        <dev:code>0..10 | Invoke-Parallel { Start-Sleep 1 } -TimeoutSeconds 3</dev:code>
        <dev:remarks>
          <maml:para>This example limits execution to 3 seconds, stopping all running script blocks and ignoring unprocessed input once the timeout is reached.</maml:para>
        </dev:remarks>
      </command:example>
      <command:example>
        <maml:title>--- Example 7: Creating new runspaces with `-UseNewRunspace` ---</maml:title>
        <dev:code>0..3 | Invoke-Parallel { [runspace]::DefaultRunspace.InstanceId } -ThrottleLimit 2
 
# Guid
# ----
# c945ae1f-4e66-4312-b23c-f3994965308e
# 1c6af45c-8727-4488-937a-4dfc1d259e9e
# c945ae1f-4e66-4312-b23c-f3994965308e
# 1c6af45c-8727-4488-937a-4dfc1d259e9e
 
0..3 | Invoke-Parallel { [runspace]::DefaultRunspace.InstanceId } -ThrottleLimit 2 -UseNewRunspace
 
# Guid
# ----
# 7a1c3871-6ce2-4b7f-ae90-fb1e92cd9678
# 2488be9e-15fe-4be2-882d-7d98b068c913
# d3dd7b5d-e7e3-457f-b6fb-def35fe837d7
# 9af7c222-061d-4c89-b073-375ee925e538</dev:code>
        <dev:remarks>
          <maml:para>This example contrasts default runspace reuse with the `-UseNewRunspace` switch, showing unique runspace IDs for each invocation in the latter case.</maml:para>
        </dev:remarks>
      </command:example>
    </command:examples>
    <command:relatedLinks>
      <maml:navigationLink>
        <maml:linkText>Online Version:</maml:linkText>
        <maml:uri>https://github.com/santisq/PSParallelPipeline</maml:uri>
      </maml:navigationLink>
      <maml:navigationLink>
        <maml:linkText>__ForEach-Object -Parallel__</maml:linkText>
        <maml:uri>https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object</maml:uri>
      </maml:navigationLink>
      <maml:navigationLink>
        <maml:linkText>__Runspaces Overview__</maml:linkText>
        <maml:uri>https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspace?view=powershellsdk-7.4.0</maml:uri>
      </maml:navigationLink>
      <maml:navigationLink>
        <maml:linkText>__Managed threading best practices__</maml:linkText>
        <maml:uri>https://learn.microsoft.com/en-us/dotnet/standard/threading/managed-threading-best-practices</maml:uri>
      </maml:navigationLink>
      <maml:navigationLink>
        <maml:linkText>__Thread-safe collections__</maml:linkText>
        <maml:uri>https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/</maml:uri>
      </maml:navigationLink>
    </command:relatedLinks>
  </command:command>
</helpItems>