Updates from: 04/05/2022 01:53:23
Service Microsoft Docs article Related commit history on GitHub Change details
Microsoft.PowerShell.Core Foreach Object (7.0) https://github.com/MicrosoftDocs/PowerShell-Docs/commits/staging/reference/7.0/Microsoft.PowerShell.Core/ForEach-Object.md
external help file: System.Management.Automation.dll-Help.xml Locale: en-US Module Name: Microsoft.PowerShell.Core Previously updated : 07/27/2021 Last updated : 04/04/2022 online version: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7&WT.mc_id=ps-gethelp schema: 2.0.0 Title: ForEach-Object
command.
By default, the parallel scriptblocks use the current working directory of the caller that started the parallel tasks.
- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
- scriptblocks. Because parallel scriptblock execution order cannot be determined, the order in
- which errors appear in the error stream is random. Likewise, messages written to other data
- streams, like warning, verbose, or information are written to those data streams in an
- indeterminate order.
-
- Terminating errors, such as exceptions, terminate the individual parallel instance of the
- scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
- termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
- to run unless they also encounter a terminating error. The terminating error is written to the
- error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
- Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
- blocks.
+ For more information, see the [NOTES](#notes) section of this article.
## EXAMPLES
Output: 5
`Output: 3` is never written because the parallel scriptblock for that iteration was terminated.
+> [!NOTE]
+> [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_
+> supported in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+ ### Example 17: Passing variables in nested parallel script ScriptBlockSet You can create a variable outside a `Foreach-Object -Parallel` scoped scriptblock and use
This cmdlet returns objects that are determined by the input.
## NOTES -- The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
- input to a **Foreach** statement. For more information about the **Foreach** statement, see
- [about_Foreach](./About/about_Foreach.md).
+The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
+input to a **Foreach** statement. For more information about the **Foreach** statement, see
+[about_Foreach](./About/about_Foreach.md).
+
+Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
+can read more about these new methods here [about_arrays](./About/about_Arrays.md)
-- Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
- can read more about these new methods here [about_arrays](./About/about_Arrays.md)
+Using `ForEach-Object -Parallel`:
- The `ForEach-Object -Parallel` parameter set uses PowerShell's internal API to run each script
- block. This is significantly more overhead than running `ForEach-Object` normally with sequential
- processing. It is important to use **Parallel** where the overhead of running in parallel is small
- compared to work the script block performs. For example:
+ block in a new runspace. This is significantly more overhead than running `ForEach-Object`
+ normally with sequential processing. It is important to use **Parallel** where the overhead of
+ running in parallel is small compared to work the script block performs. For example:
- Compute intensive scripts on multi-core machines - Scripts that spend time waiting for results or doing file operations
This cmdlet returns objects that are determined by the input.
the parallel scripts are trivial. Experiment with **Parallel** to discover where it can be beneficial.
+- When running in parallel, objects decorated with **ScriptProperties** or **ScriptMethods** cannot
+ be guaranteed to function correctly if they are run in a different runspace than the scripts were
+ originally attached to them.
+
+ Scriptblock invocation always attempts to run in its _home_ runspace, regardless of where it's
+ actually invoked. However, `ForEach-Object -Parallel` creates temporary runspaces that get deleted
+ after use, so there's no runspace for the scripts to execute in anymore.
+
+ This behavior can work as long as the _home_ runspace still exists. However, you may not get
+ the desired result if the script is dependent on external variables that are only present in the
+ caller's runspace and not the _home_ runspace.
+
+- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
+ scriptblocks. Because parallel scriptblock execution order is non-deterministic, the order in
+ which errors appear in the error stream is random. Likewise, messages written to other data
+ streams, like warning, verbose, or information are written to those data streams in an
+ indeterminate order.
+
+ Terminating errors, such as exceptions, terminate the individual parallel instance of the
+ scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
+ termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
+ to run unless they also encounter a terminating error. The terminating error is written to the
+ error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
+ Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
+ blocks.
+ - [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_ supported
- in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+ in parallel scenarios even with the `$using:` keyword.
> [!IMPORTANT] > The `ForEach-Object -Parallel` parameter set runs script blocks in parallel on separate process
This cmdlet returns objects that are determined by the input.
> thread to each running script block thread. Since the script blocks run in different threads, > the object variables passed by reference must be used safely. Generally it is safe to read from > referenced objects that don't change. But if the object state is being modified then you must
- > used thread safe objects, such as .Net **System.Collection.Concurrent** types (See Example 11).
+ > used thread safe objects, such as .NET **System.Collection.Concurrent** types (See Example 11).
## RELATED LINKS
Microsoft.PowerShell.Core Foreach Object (7.1) https://github.com/MicrosoftDocs/PowerShell-Docs/commits/staging/reference/7.1/Microsoft.PowerShell.Core/ForEach-Object.md
external help file: System.Management.Automation.dll-Help.xml Locale: en-US Module Name: Microsoft.PowerShell.Core Previously updated : 07/27/2021 Last updated : 04/04/2022 online version: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.1&WT.mc_id=ps-gethelp schema: 2.0.0 Title: ForEach-Object
ForEach-Object [-InputObject <PSObject>] [-MemberName] <String> [-ArgumentList <
### ParallelParameterSet ```
-ForEach-Object -Parallel <scriptblock> [-InputObject <PSObject>] [-ThrottleLimit <int>]
- [-UseNewRunspace] [-TimeoutSeconds <int>] [-AsJob] [-WhatIf] [-Confirm] [<CommonParameters>]
+ForEach-Object [-InputObject <PSObject>] -Parallel <ScriptBlock> [-ThrottleLimit <Int32>]
+ [-TimeoutSeconds <Int32>] [-AsJob] [-WhatIf] [-Confirm] [<CommonParameters>]
``` ## DESCRIPTION
command.
By default, the parallel scriptblocks use the current working directory of the caller that started the parallel tasks.
- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
- scriptblocks. Because parallel scriptblock execution order cannot be determined, the order in
- which errors appear in the error stream is random. Likewise, messages written to other data
- streams, like warning, verbose, or information are written to those data streams in an
- indeterminate order.
-
- Terminating errors, such as exceptions, terminate the individual parallel instance of the
- scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
- termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
- to run unless they also encounter a terminating error. The terminating error is written to the
- error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
- Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
- blocks.
+ For more information, see the [NOTES](#notes) section of this article.
## EXAMPLES
Output: 5
`Output: 3` is never written because the parallel scriptblock for that iteration was terminated.
+> [!NOTE]
+> [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_
+> supported in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+ ### Example 17: Passing variables in nested parallel script ScriptBlockSet You can create a variable outside a `Foreach-Object -Parallel` scoped scriptblock and use
This cmdlet returns objects that are determined by the input.
## NOTES -- The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
- input to a **Foreach** statement. For more information about the **Foreach** statement, see
- [about_Foreach](./About/about_Foreach.md).
+The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
+input to a **Foreach** statement. For more information about the **Foreach** statement, see
+[about_Foreach](./About/about_Foreach.md).
+
+Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
+can read more about these new methods here [about_arrays](./About/about_Arrays.md)
-- Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
- can read more about these new methods here [about_arrays](./About/about_Arrays.md)
+Using `ForEach-Object -Parallel`:
- The `ForEach-Object -Parallel` parameter set uses PowerShell's internal API to run each script
- block. This is significantly more overhead than running `ForEach-Object` normally with sequential
- processing. It is important to use **Parallel** where the overhead of running in parallel is small
- compared to work the script block performs. For example:
+ block in a new runspace. This is significantly more overhead than running `ForEach-Object`
+ normally with sequential processing. It is important to use **Parallel** where the overhead of
+ running in parallel is small compared to work the script block performs. For example:
- Compute intensive scripts on multi-core machines - Scripts that spend time waiting for results or doing file operations
This cmdlet returns objects that are determined by the input.
the parallel scripts are trivial. Experiment with **Parallel** to discover where it can be beneficial.
+- When running in parallel, objects decorated with **ScriptProperties** or **ScriptMethods** cannot
+ be guaranteed to function correctly if they are run in a different runspace than the scripts were
+ originally attached to them.
+
+ Scriptblock invocation always attempts to run in its _home_ runspace, regardless of where it's
+ actually invoked. However, `ForEach-Object -Parallel` creates temporary runspaces that get deleted
+ after use, so there's no runspace for the scripts to execute in anymore.
+
+ This behavior can work as long as the _home_ runspace still exists. However, you may not get
+ the desired result if the script is dependent on external variables that are only present in the
+ caller's runspace and not the _home_ runspace.
+
+- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
+ scriptblocks. Because parallel scriptblock execution order is non-deterministic, the order in
+ which errors appear in the error stream is random. Likewise, messages written to other data
+ streams, like warning, verbose, or information are written to those data streams in an
+ indeterminate order.
+
+ Terminating errors, such as exceptions, terminate the individual parallel instance of the
+ scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
+ termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
+ to run unless they also encounter a terminating error. The terminating error is written to the
+ error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
+ Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
+ blocks.
+ - [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_ supported
- in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+ in parallel scenarios even with the `$using:` keyword.
> [!IMPORTANT] > The `ForEach-Object -Parallel` parameter set runs script blocks in parallel on separate process
This cmdlet returns objects that are determined by the input.
> thread to each running script block thread. Since the script blocks run in different threads, > the object variables passed by reference must be used safely. Generally it is safe to read from > referenced objects that don't change. But if the object state is being modified then you must
- > used thread safe objects, such as .Net **System.Collection.Concurrent** types (See Example 11).
+ > used thread safe objects, such as .NET **System.Collection.Concurrent** types (See Example 11).
## RELATED LINKS
Microsoft.PowerShell.Core Foreach Object (7.2) https://github.com/MicrosoftDocs/PowerShell-Docs/commits/staging/reference/7.2/Microsoft.PowerShell.Core/ForEach-Object.md
external help file: System.Management.Automation.dll-Help.xml Locale: en-US Module Name: Microsoft.PowerShell.Core Previously updated : 07/27/2021 Last updated : 04/04/2022 online version: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.2&WT.mc_id=ps-gethelp schema: 2.0.0 Title: ForEach-Object
ForEach-Object [-InputObject <PSObject>] [-MemberName] <String> [-ArgumentList <
### ParallelParameterSet ```
-ForEach-Object -Parallel <scriptblock> [-InputObject <PSObject>] [-ThrottleLimit <int>]
- [-UseNewRunspace] [-TimeoutSeconds <int>] [-AsJob] [-WhatIf] [-Confirm] [<CommonParameters>]
+ForEach-Object [-InputObject <PSObject>] -Parallel <ScriptBlock> [-ThrottleLimit <Int32>]
+ [-TimeoutSeconds <Int32>] [-AsJob] [-WhatIf] [-Confirm] [<CommonParameters>]
``` ## DESCRIPTION
command.
By default, the parallel scriptblocks use the current working directory of the caller that started the parallel tasks.
- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
- scriptblocks. Because parallel scriptblock execution order cannot be determined, the order in
- which errors appear in the error stream is random. Likewise, messages written to other data
- streams, like warning, verbose, or information are written to those data streams in an
- indeterminate order.
-
- Terminating errors, such as exceptions, terminate the individual parallel instance of the
- scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
- termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
- to run unless they also encounter a terminating error. The terminating error is written to the
- error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
- Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
- blocks.
+ For more information, see the [NOTES](#notes) section of this article.
## EXAMPLES
operator `$_`. It uses the dot syntax to specify the method and parentheses to e
argument. The second command uses the **MemberName** parameter to specify the **Split** method and the
-**ArgumentList** parameter to identify the dot (".") as the split delimiter.
+**ArgumentList** parameter to identify the dot (`.`) as the split delimiter.
The third command uses the **Foreach** alias of the `ForEach-Object` cmdlet and omits the names of the **MemberName** and **ArgumentList** parameters, which are optional.
Output: 5
> [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_ > supported in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+### Example 17: Passing variables in nested parallel script ScriptBlockSet
+
+You can create a variable outside a `Foreach-Object -Parallel` scoped scriptblock and use
+it inside the scriptblock with the `$using` keyword.
+
+```powershell
+$test1 = 'TestA'
+1..2 | Foreach-Object -Parallel {
+ $using:test1
+}
+```
+
+```Output
+TestA
+TestA
+```
+
+```powershell
+# You CANNOT create a variable inside a scoped scriptblock
+# to be used in a nested foreach parallel scriptblock.
+$test1 = 'TestA'
+1..2 | Foreach-Object -Parallel {
+ $using:test1
+ $test2 = 'TestB'
+ 1..2 | Foreach-Object -Parallel {
+ $using:test2
+ }
+}
+```
+
+```Output
+Line |
+ 2 | 1..2 | Foreach-Object -Parallel {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | The value of the using variable '$using:test2' cannot be retrieved because it has not been set in the local session.
+```
+
+The nested scriptblock can't access the `$test2` variable and an error is thrown.
+ ## PARAMETERS ### -ArgumentList
This cmdlet returns objects that are determined by the input.
## NOTES -- The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
- input to a **Foreach** statement. For more information about the **Foreach** statement, see
- [about_Foreach](./About/about_Foreach.md).
+The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
+input to a **Foreach** statement. For more information about the **Foreach** statement, see
+[about_Foreach](./About/about_Foreach.md).
-- Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
- can read more about these new methods here [about_arrays](./About/about_Arrays.md)
+Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
+can read more about these new methods here [about_arrays](./About/about_Arrays.md)
+
+Using `ForEach-Object -Parallel`:
- The `ForEach-Object -Parallel` parameter set uses PowerShell's internal API to run each script
- block. This is significantly more overhead than running `ForEach-Object` normally with sequential
- processing. It is important to use **Parallel** where the overhead of running in parallel is small
- compared to work the script block performs. For example:
+ block in a new runspace. This is significantly more overhead than running `ForEach-Object`
+ normally with sequential processing. It is important to use **Parallel** where the overhead of
+ running in parallel is small compared to work the script block performs. For example:
- Compute intensive scripts on multi-core machines - Scripts that spend time waiting for results or doing file operations
This cmdlet returns objects that are determined by the input.
the parallel scripts are trivial. Experiment with **Parallel** to discover where it can be beneficial.
+- When running in parallel, objects decorated with **ScriptProperties** or **ScriptMethods** cannot
+ be guaranteed to function correctly if they are run in a different runspace than the scripts were
+ originally attached to them.
+
+ Scriptblock invocation always attempts to run in its _home_ runspace, regardless of where it's
+ actually invoked. However, `ForEach-Object -Parallel` creates temporary runspaces that get deleted
+ after use, so there's no runspace for the scripts to execute in anymore.
+
+ This behavior can work as long as the _home_ runspace still exists. However, you may not get
+ the desired result if the script is dependent on external variables that are only present in the
+ caller's runspace and not the _home_ runspace.
+
+- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
+ scriptblocks. Because parallel scriptblock execution order is non-deterministic, the order in
+ which errors appear in the error stream is random. Likewise, messages written to other data
+ streams, like warning, verbose, or information are written to those data streams in an
+ indeterminate order.
+
+ Terminating errors, such as exceptions, terminate the individual parallel instance of the
+ scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
+ termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
+ to run unless they also encounter a terminating error. The terminating error is written to the
+ error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
+ Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
+ blocks.
+ - [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_ supported
- in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+ in parallel scenarios even with the `$using:` keyword.
> [!IMPORTANT] > The `ForEach-Object -Parallel` parameter set runs script blocks in parallel on separate process
This cmdlet returns objects that are determined by the input.
> thread to each running script block thread. Since the script blocks run in different threads, > the object variables passed by reference must be used safely. Generally it is safe to read from > referenced objects that don't change. But if the object state is being modified then you must
- > used thread safe objects, such as .Net **System.Collection.Concurrent** types (See Example 11).
+ > used thread safe objects, such as .NET **System.Collection.Concurrent** types (See Example 11).
## RELATED LINKS
Microsoft.PowerShell.Core Foreach Object (7.3) https://github.com/MicrosoftDocs/PowerShell-Docs/commits/staging/reference/7.3/Microsoft.PowerShell.Core/ForEach-Object.md
external help file: System.Management.Automation.dll-Help.xml Locale: en-US Module Name: Microsoft.PowerShell.Core Previously updated : 07/27/2021 Last updated : 04/04/2022 online version: https://docs.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.3&WT.mc_id=ps-gethelp schema: 2.0.0 Title: ForEach-Object
ForEach-Object [-InputObject <PSObject>] [-MemberName] <String> [-ArgumentList <
### ParallelParameterSet ```
-ForEach-Object -Parallel <scriptblock> [-InputObject <PSObject>] [-ThrottleLimit <int>]
- [-UseNewRunspace] [-TimeoutSeconds <int>] [-AsJob] [-WhatIf] [-Confirm] [<CommonParameters>]
+ForEach-Object [-InputObject <PSObject>] -Parallel <ScriptBlock> [-ThrottleLimit <Int32>]
+ [-TimeoutSeconds <Int32>] [-AsJob] [-WhatIf] [-Confirm] [<CommonParameters>]
``` ## DESCRIPTION
command.
By default, the parallel scriptblocks use the current working directory of the caller that started the parallel tasks.
- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
- scriptblocks. Because parallel scriptblock execution order cannot be determined, the order in
- which errors appear in the error stream is random. Likewise, messages written to other data
- streams, like warning, verbose, or information are written to those data streams in an
- indeterminate order.
-
- Terminating errors, such as exceptions, terminate the individual parallel instance of the
- scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
- termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
- to run unless they also encounter a terminating error. The terminating error is written to the
- error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
- Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
- blocks.
+ For more information, see the [NOTES](#notes) section of this article.
## EXAMPLES
operator `$_`. It uses the dot syntax to specify the method and parentheses to e
argument. The second command uses the **MemberName** parameter to specify the **Split** method and the
-**ArgumentList** parameter to identify the dot (".") as the split delimiter.
+**ArgumentList** parameter to identify the dot (`.`) as the split delimiter.
The third command uses the **Foreach** alias of the `ForEach-Object` cmdlet and omits the names of the **MemberName** and **ArgumentList** parameters, which are optional.
Output: 5
> [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_ > supported in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+### Example 17: Passing variables in nested parallel script ScriptBlockSet
+
+You can create a variable outside a `Foreach-Object -Parallel` scoped scriptblock and use
+it inside the scriptblock with the `$using` keyword.
+
+```powershell
+$test1 = 'TestA'
+1..2 | Foreach-Object -Parallel {
+ $using:test1
+}
+```
+
+```Output
+TestA
+TestA
+```
+
+```powershell
+# You CANNOT create a variable inside a scoped scriptblock
+# to be used in a nested foreach parallel scriptblock.
+$test1 = 'TestA'
+1..2 | Foreach-Object -Parallel {
+ $using:test1
+ $test2 = 'TestB'
+ 1..2 | Foreach-Object -Parallel {
+ $using:test2
+ }
+}
+```
+
+```Output
+Line |
+ 2 | 1..2 | Foreach-Object -Parallel {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | The value of the using variable '$using:test2' cannot be retrieved because it has not been set in the local session.
+```
+
+The nested scriptblock can't access the `$test2` variable and an error is thrown.
+ ## PARAMETERS ### -ArgumentList
This cmdlet returns objects that are determined by the input.
## NOTES -- The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
- input to a **Foreach** statement. For more information about the **Foreach** statement, see
- [about_Foreach](./About/about_Foreach.md).
+The `ForEach-Object` cmdlet works much like the **Foreach** statement, except that you cannot pipe
+input to a **Foreach** statement. For more information about the **Foreach** statement, see
+[about_Foreach](./About/about_Foreach.md).
-- Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
- can read more about these new methods here [about_arrays](./About/about_Arrays.md)
+Starting in PowerShell 4.0, `Where` and `ForEach` methods were added for use with collections. You
+can read more about these new methods here [about_arrays](./About/about_Arrays.md)
+
+Using `ForEach-Object -Parallel`:
- The `ForEach-Object -Parallel` parameter set uses PowerShell's internal API to run each script
- block. This is significantly more overhead than running `ForEach-Object` normally with sequential
- processing. It is important to use **Parallel** where the overhead of running in parallel is small
- compared to work the script block performs. For example:
+ block in a new runspace. This is significantly more overhead than running `ForEach-Object`
+ normally with sequential processing. It is important to use **Parallel** where the overhead of
+ running in parallel is small compared to work the script block performs. For example:
- Compute intensive scripts on multi-core machines - Scripts that spend time waiting for results or doing file operations
This cmdlet returns objects that are determined by the input.
the parallel scripts are trivial. Experiment with **Parallel** to discover where it can be beneficial.
+- When running in parallel, objects decorated with **ScriptProperties** or **ScriptMethods** cannot
+ be guaranteed to function correctly if they are run in a different runspace than the scripts were
+ originally attached to them.
+
+ Scriptblock invocation always attempts to run in its _home_ runspace, regardless of where it's
+ actually invoked. However, `ForEach-Object -Parallel` creates temporary runspaces that get deleted
+ after use, so there's no runspace for the scripts to execute in anymore.
+
+ This behavior can work as long as the _home_ runspace still exists. However, you may not get
+ the desired result if the script is dependent on external variables that are only present in the
+ caller's runspace and not the _home_ runspace.
+
+- Non-terminating errors are written to the cmdlet error stream as they occur in parallel running
+ scriptblocks. Because parallel scriptblock execution order is non-deterministic, the order in
+ which errors appear in the error stream is random. Likewise, messages written to other data
+ streams, like warning, verbose, or information are written to those data streams in an
+ indeterminate order.
+
+ Terminating errors, such as exceptions, terminate the individual parallel instance of the
+ scriptblocks in which they occur. A terminating error in one scriptblocks may not cause the
+ termination of the `Foreach-Object` cmdlet. The other scriptblocks, running in parallel, continue
+ to run unless they also encounter a terminating error. The terminating error is written to the
+ error data stream as an **ErrorRecord** with a **FullyQualifiedErrorId** of `PSTaskException`.
+ Terminating errors can be converted to non-terminating errors using PowerShell try/catch or trap
+ blocks.
+ - [PipelineVariable](About/about_CommonParameters.md) common parameter variables are _not_ supported
- in `Foreach-Object -Parallel` scenarios even with the `$using:` keyword.
+ in parallel scenarios even with the `$using:` keyword.
> [!IMPORTANT] > The `ForEach-Object -Parallel` parameter set runs script blocks in parallel on separate process
This cmdlet returns objects that are determined by the input.
> thread to each running script block thread. Since the script blocks run in different threads, > the object variables passed by reference must be used safely. Generally it is safe to read from > referenced objects that don't change. But if the object state is being modified then you must
- > used thread safe objects, such as .Net **System.Collection.Concurrent** types (See Example 11).
+ > used thread safe objects, such as .NET **System.Collection.Concurrent** types (See Example 11).
## RELATED LINKS