ForEach-Object
Выполняет операцию по каждому элементу в коллекции входных объектов.
Синтаксис
ForEach-Object
[-InputObject <PSObject>]
[-Begin <ScriptBlock>]
[-Process] <ScriptBlock[]>
[-End <ScriptBlock>]
[-RemainingScripts <ScriptBlock[]>]
[-WhatIf]
[-Confirm]
[<CommonParameters>]
ForEach-Object
[-InputObject <PSObject>]
[-MemberName] <String>
[-ArgumentList <Object[]>]
[-WhatIf]
[-Confirm]
[<CommonParameters>]
ForEach-Object
-Parallel <scriptblock>
[-InputObject <psobject>]
[-ThrottleLimit <int>]
[-TimeoutSeconds <int>]
[-AsJob]
[-UseNewRunspace]
[-WhatIf]
[-Confirm]
[<CommonParameters>]
Описание
Командлет ForEach-Object
выполняет операцию по каждому элементу в коллекции входных объектов. Входные объекты можно передать в командлет или указать с помощью параметра InputObject.
Начиная с Windows PowerShell 3.0, существует два разных способа создания команды ForEach-Object
.
блок скрипта. Чтобы указать операцию, можно использовать блок скрипта. В блоке скрипта используйте переменную
$_
для представления текущего объекта. Блок скрипта — это значение параметра процесса. Блок скрипта может содержать любой скрипт PowerShell.Например, следующая команда получает значение свойства ProcessName каждого процесса на компьютере.
Get-Process | ForEach-Object {$_.ProcessName}
ForEach-Object
поддерживает блокиbegin
,process
иend
, как описано в about_functions.Заметка
Блоки скрипта выполняются в области вызывающего абонента. Поэтому блоки имеют доступ к переменным в этой области и могут создавать новые переменные, которые сохраняются в этой области после завершения командлета.
инструкции operation. Вы также можете написать инструкцию операции, которая гораздо больше похожа на естественный язык. Инструкцию операции можно использовать для указания значения свойства или вызова метода. Инструкции операций появились в Windows PowerShell 3.0.
Например, следующая команда также получает значение свойства ProcessName каждого процесса на компьютере.
Get-Process | ForEach-Object ProcessName
блок скрипта параллельного выполнения. Начиная с PowerShell 7.0, третий набор параметров доступен для параллельного запуска каждого блока скрипта. Параметр ThrottleLimit ограничивает количество параллельных скриптов, выполняемых одновременно. Как и раньше, используйте переменную
$_
для представления текущего входного объекта в блоке скрипта. Используйте ключевое слово$using:
для передачи ссылок на переменные в запущенный скрипт.В PowerShell 7 создается новое пространство выполнения для каждой итерации цикла, чтобы обеспечить максимальную изоляцию. Это может быть большой уровень производительности и попадания ресурсов, если работа, выполняемая вами, невелика по сравнению с созданием новых пространств выполнения или при наличии большого количества итераций, выполняющих значительную работу. По состоянию на PowerShell 7.1 пространства выполнения из пула пространств runspace повторно используются по умолчанию. Параметр ThrottleLimit задает размер пула пространств выполнения. Размер пула runspace по умолчанию — 5. Вы по-прежнему можете создать новое пространство выполнения для каждой итерации с помощью параметра UseNewRunspace.
По умолчанию параллельные скрипты используют текущий рабочий каталог вызывающего объекта, запускающего параллельные задачи.
Дополнительные сведения см. в разделе NOTES этой статьи.
Примеры
Пример 1. Разделение целых чисел в массиве
Этот пример принимает массив из трех целых чисел и делит каждый из них на 1024.
30000, 56798, 12432 | ForEach-Object -Process {$_/1024}
29.296875
55.466796875
12.140625
Пример 2. Получение длины всех файлов в каталоге
В этом примере файлы и каталоги в каталоге установки PowerShell $PSHOME
.
Get-ChildItem $PSHOME |
ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }}
Если объект не является каталогом, блок скрипта получает имя файла, делит значение его свойства Length на 1024, а также добавляет пробел (""), чтобы отделить его от следующей записи. Командлет использует свойство PSISContainer, чтобы определить, является ли объект каталогом.
Пример 3. Работа с последними событиями системы
В этом примере записывается 1000 последних событий из журнала событий системы в текстовый файл. Текущее время отображается до и после обработки событий.
Get-EventLog -LogName System -Newest 1000 |
ForEach-Object -Begin {Get-Date} -Process {
Out-File -FilePath Events.txt -Append -InputObject $_.Message
} -End {Get-Date}
Get-EventLog
возвращает 1000 последних событий из журнала событий системы и передает их командлету ForEach-Object
. Параметр Begin отображает текущую дату и время. Затем параметр процесса использует командлет Out-File
для создания текстового файла с именем events.txt и сохраняет свойство сообщения каждого события в этом файле. Наконец, параметр end используется для отображения даты и времени после завершения обработки.
Пример 4. Изменение значения раздела реестра
В этом примере изменяется значение записи реестра RemotePath во всех вложенных разделах в разделе HKCU:\Network
в верхний регистр текста.
Get-ItemProperty -Path HKCU:\Network\* |
ForEach-Object {
Set-ItemProperty -Path $_.PSPath -Name RemotePath -Value $_.RemotePath.ToUpper()
}
Этот формат можно использовать для изменения формы или содержимого значения записи реестра.
Каждый подраздел в ключе сети представляет сопоставленный сетевой диск, который повторно подключается при входе. Запись RemotePath содержит UNC-путь подключенного диска. Например, если вы сопоставляете диск E:
с \\Server\Share
, то в HKCU:\Network
создается подключ E HKCU:\Network
со значением реестра remotePath RemotePath значением \\Server\Share
.
Команда использует командлет Get-ItemProperty
для получения всех подразделов ключа сети и командлета Set-ItemProperty
для изменения значения записи реестра RemotePath в каждом разделе. В команде Set-ItemProperty
путь — это значение свойства PSPath раздела реестра. Это свойство объекта Microsoft .NET Framework, представляющего раздел реестра, а не запись реестра. Команда использует метод ToUpper() значения RemotePath, который является строковым REG_SZ.
Так как Set-ItemProperty
изменяет свойство каждого ключа, для доступа к свойству требуется командлет ForEach-Object
.
Пример 5. Использование автоматической переменной $null
В этом примере показан эффект подключения $null
автоматической переменной к командлету ForEach-Object
.
1, 2, $null, 4 | ForEach-Object {"Hello"}
Hello
Hello
Hello
Hello
Так как PowerShell обрабатывает $null
как явный заполнитель, командлет ForEach-Object
создает значение для $null
, как и для других объектов, которые передаются в него.
Пример 6. Получение значений свойств
В этом примере возвращается значение свойства Path всех установленных модулей PowerShell с помощью параметра MemberName командлета ForEach-Object
.
Get-Module -ListAvailable | ForEach-Object -MemberName Path
Get-Module -ListAvailable | Foreach Path
Вторая команда эквивалентна первой. Он использует псевдоним Foreach
командлета ForEach-Object
и не указывает имя параметра MemberName, который является необязательным.
Командлет ForEach-Object
полезен для получения значений свойств, так как он получает значение без изменения типа, в отличие от командлетов формата или командлета Select-Object
, который изменяет тип значения свойства.
Пример 7. Разделение имен модулей на имена компонентов
В этом примере показано три способа разделения двух точечного модуля на их имена компонентов. Команды вызывают метод Split строк. Три команды используют другой синтаксис, но они эквивалентны и взаимозаменяемы. Выходные данные одинаковы для всех трех случаев.
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" |
ForEach-Object {$_.Split(".")}
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" |
ForEach-Object -MemberName Split -ArgumentList "."
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" |
Foreach Split "."
Microsoft
PowerShell
Core
Microsoft
PowerShell
Host
Первая команда использует традиционный синтаксис, который включает блок скрипта и текущий оператор объекта $_
. Он использует синтаксис точки для указания метода и круглых скобок для заключения аргумента разделителя.
Вторая команда использует параметр MemberName для указания метода split и параметра ArgumentList для идентификации точки (.
) в качестве разделителя разбиения.
Третья команда использует псевдоним foreach командлета ForEach-Object
и не указывает имена параметров MemberName и ArgumentList, которые являются необязательными.
Пример 8. Использование ForEach-Object с двумя блоками скриптов
В этом примере мы передаваем два блока скрипта позиционально. Все блоки скрипта привязываются к параметру процесса. Однако они рассматриваются как будто они были переданы в параметры Begin и Process.
1..2 | ForEach-Object { 'begin' } { 'process' }
begin
process
process
Пример 9. Использование ForEach-Object с более чем двумя блоками скриптов
В этом примере мы передаваем четыре блока скрипта позиционально. Все блоки скрипта привязываются к параметру процесса. Однако они обрабатываются так, как если бы они были переданы в параметры Begin, Processи End.
1..2 | ForEach-Object { 'begin' } { 'process A' } { 'process B' } { 'end' }
begin
process A
process B
process A
process B
end
Заметка
Первый блок скрипта всегда сопоставляется с блоком begin
, последний блок сопоставляется с блоком end
, а два средних блока сопоставляются с блоком process
.
Пример 10. Запуск нескольких блоков скриптов для каждого элемента конвейера
Как показано в предыдущем примере, несколько блоков скриптов, передаваемых с помощью параметра процесса, сопоставляются с параметрами Begin и End. Чтобы избежать этого сопоставления, необходимо указать явные значения для параметров Begin и End.
1..2 | ForEach-Object -Begin $null -Process { 'one' }, { 'two' }, { 'three' } -End $null
one
two
three
one
two
three
Пример 11. Выполнение медленного скрипта в параллельных пакетах
В этом примере выполняется блок скрипта, вычисляющий строку и спящий режим в течение одной секунды.
$Message = "Output:"
1..8 | ForEach-Object -Parallel {
"$using:Message $_"
Start-Sleep 1
} -ThrottleLimit 4
Output: 1
Output: 2
Output: 3
Output: 4
Output: 5
Output: 6
Output: 7
Output: 8
Значение параметра ThrottleLimit имеет значение 4, чтобы входные данные обрабатывались в пакетах из четырех.
Ключевое слово $using:
используется для передачи переменной $Message
в каждый блок параллельных скриптов.
Пример 12. Параллельное получение записей журнала
В этом примере извлекается 50 000 записей журналов из 5 системных журналов на локальном компьютере Windows.
$logNames = 'Security', 'Application', 'System', 'Windows PowerShell',
'Microsoft-Windows-Store/Operational'
$logEntries = $logNames | ForEach-Object -Parallel {
Get-WinEvent -LogName $_ -MaxEvents 10000
} -ThrottleLimit 5
$logEntries.Count
50000
Параметр Parallel задает блок скрипта, который выполняется параллельно для каждого имени входного журнала. Параметр ThrottleLimit гарантирует, что все пять блоков скриптов выполняются одновременно.
Пример 13. Параллельное выполнение в качестве задания
В этом примере создается задание, которое выполняет блок скрипта параллельно, два за раз.
PS> $job = 1..10 | ForEach-Object -Parallel {
"Output: $_"
Start-Sleep 1
} -ThrottleLimit 2 -AsJob
PS> $job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
23 Job23 PSTaskJob Running True PowerShell …
PS> $job.ChildJobs
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
24 Job24 PSTaskChildJob Completed True PowerShell …
25 Job25 PSTaskChildJob Completed True PowerShell …
26 Job26 PSTaskChildJob Running True PowerShell …
27 Job27 PSTaskChildJob Running True PowerShell …
28 Job28 PSTaskChildJob NotStarted False PowerShell …
29 Job29 PSTaskChildJob NotStarted False PowerShell …
30 Job30 PSTaskChildJob NotStarted False PowerShell …
31 Job31 PSTaskChildJob NotStarted False PowerShell …
32 Job32 PSTaskChildJob NotStarted False PowerShell …
33 Job33 PSTaskChildJob NotStarted False PowerShell …
Параметр ThrottleLimit ограничивает количество блоков параллельных скриптов, выполняемых одновременно. Параметр AsJob приводит к тому, что командлет ForEach-Object
возвращает объект задания вместо потоковой передачи выходных данных в консоль. Переменная $job
получает объект задания, который собирает выходные данные и отслеживает состояние выполнения. Свойство $job.ChildJobs
содержит дочерние задания, которые выполняют блоки параллельных скриптов.
Пример 14. Использование ссылок на надежные потоки переменных
В этом примере блоки скриптов вызываются параллельно для сбора уникальных именованных объектов Process.
$threadSafeDictionary = [System.Collections.Concurrent.ConcurrentDictionary[string,object]]::new()
Get-Process | ForEach-Object -Parallel {
$dict = $using:threadSafeDictionary
$dict.TryAdd($_.ProcessName, $_)
}
$threadSafeDictionary["pwsh"]
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
82 82.87 130.85 15.55 2808 2 pwsh
Один экземпляр объекта ConcurrentDictionary передается каждому блоку скрипта для сбора объектов. Так как ParallelDictionary является потокобезопасной, он безопасно изменяться каждым параллельным скриптом. Непотокобезопасный объект, например System.Collections.Generic.Dictionary, не будет безопасным для использования здесь.
Заметка
Этот пример является неэффективным использованием параметра Parallel. Скрипт добавляет входной объект в параллельный объект словаря. Это тривиальный и не стоит затраты на вызов каждого скрипта в отдельном потоке. Выполнение ForEach-Object
без параллельного коммутатора является более эффективным и быстрым. Этот пример предназначен только для демонстрации того, как использовать потокобезопасные переменные.
Пример 15. Написание ошибок с параллельным выполнением
В этом примере выполняется запись в поток ошибок параллельно, где порядок записанных ошибок является случайным.
1..3 | ForEach-Object -Parallel {
Write-Error "Error: $_"
}
Write-Error: Error: 1
Write-Error: Error: 3
Write-Error: Error: 2
Пример 16. Завершение ошибок параллельного выполнения
В этом примере показана завершающая ошибка в одном параллельном запущенном блоке скрипта.
1..5 | ForEach-Object -Parallel {
if ($_ -eq 3)
{
throw "Terminating Error: $_"
}
Write-Output "Output: $_"
}
Exception: Terminating Error: 3
Output: 1
Output: 4
Output: 2
Output: 5
Output: 3
никогда не записывается, так как параллельный блок скрипта для этой итерации был завершен.
Заметка
PipelineVariable общие переменные параметров не поддерживаются в сценариях Foreach-Object -Parallel
даже с ключевым словом $using:
.
Пример 17. Передача переменных в вложенный параллельный скрипт ScriptBlockSet
Вы можете создать переменную за пределами Foreach-Object -Parallel
области скрипта и использовать ее внутри скриптблока с ключевым словом $using
.
$test1 = 'TestA'
1..2 | Foreach-Object -Parallel {
$using:test1
}
TestA
TestA
# 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
}
}
Line |
2 | 1..2 | Foreach-Object -Parallel {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
| The value of the using variable '$using:test2' can't be retrieved because it has
| not been set in the local session.
Вложенный блок скриптов не может получить доступ к переменной $test2
и возникает ошибка.
Пример 18. Создание нескольких заданий, выполняющих скрипты параллельно
Параметр ThrottleLimit ограничивает количество параллельных скриптов, выполняемых во время каждого экземпляра ForEach-Object -Parallel
. Это не ограничивает количество заданий, которые можно создать при использовании параметра AsJob. Так как задания выполняются одновременно, можно создать несколько параллельных заданий, каждое из которых выполняется до ограничения числа одновременных блокировок скриптов.
$jobs = for ($i=0; $i -lt 10; $i++) {
1..10 | ForEach-Object -Parallel {
./RunMyScript.ps1
} -AsJob -ThrottleLimit 5
}
$jobs | Receive-Job -Wait
В этом примере создается 10 выполняемых заданий. Каждое задание выполняется не более 5 скриптов одновременно. Общее количество экземпляров, выполняющихся одновременно, ограничено 50 (10 заданий раз ThrottleLimit 5).
Параметры
-ArgumentList
Задает массив аргументов для вызова метода. Дополнительные сведения о поведении ArgumentListсм. в about_Splatting.
Этот параметр появился в Windows PowerShell 3.0.
Тип: | Object[] |
Aliases: | Args |
Position: | Named |
Default value: | None |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-AsJob
Вызывает параллельное вызов в качестве задания PowerShell. Один объект задания возвращается вместо выходных данных из выполняемых блоков скриптов. Объект задания содержит дочерние задания для каждого блока параллельных скриптов, который выполняется. Объект задания можно использовать с любым из командлетов заданий PowerShell для просмотра состояния выполнения и получения данных.
Этот параметр появился в PowerShell 7.0.
Тип: | SwitchParameter |
Position: | Named |
Default value: | None |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-Begin
Задает блок скрипта, который выполняется перед обработкой входных объектов этого командлета. Этот блок скрипта выполняется только один раз для всего конвейера. Дополнительные сведения о блоке begin
см. в about_Functions.
Тип: | ScriptBlock |
Position: | Named |
Default value: | None |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-Confirm
Запрашивает подтверждение перед запуском командлета.
Тип: | SwitchParameter |
Aliases: | cf |
Position: | Named |
Default value: | False |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-End
Указывает блок скрипта, который выполняется после этого командлета, обрабатывает все входные объекты. Этот блок скрипта выполняется только один раз для всего конвейера. Дополнительные сведения о блоке end
см. в about_Functions.
Тип: | ScriptBlock |
Position: | Named |
Default value: | None |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-InputObject
Указывает входные объекты.
ForEach-Object
запускает блок скрипта или инструкцию операции для каждого входного объекта. Введите переменную, содержащую объекты, или введите команду или выражение, которое получает объекты.
При использовании параметра InputObject с ForEach-Object
вместо ForEach-Object
результаты команды piping InputObject рассматривается как один объект. Это верно, даже если значение является коллекцией, которая является результатом команды, например -InputObject (Get-Process)
.
Так как InputObject не могут возвращать отдельные свойства из массива или коллекции объектов, рекомендуется использовать ForEach-Object
для выполнения операций с коллекцией объектов для тех объектов, которые имеют определенные значения в определенных свойствах, используйте ForEach-Object
в конвейере, как показано в примерах этого раздела.
Тип: | PSObject |
Position: | Named |
Default value: | None |
Обязательно: | False |
Принять входные данные конвейера: | True |
Принять подстановочные знаки: | False |
-MemberName
Указывает имя свойства члена, которое нужно получить или вызвать метод-член. Элементы должны быть элементами экземпляра, а не статическими.
Подстановочные знаки разрешены, но работают только в том случае, если результирующая строка разрешает уникальное значение.
Например, при запуске Get-Process | ForEach -MemberName *Name
шаблон подстановочного знака соответствует нескольким членам, что приводит к сбою команды.
Этот параметр появился в Windows PowerShell 3.0.
Тип: | String |
Position: | 0 |
Default value: | None |
Обязательно: | True |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | True |
-Parallel
Задает блок скрипта, используемый для параллельной обработки входных объектов. Введите блок скрипта, описывающий операцию.
Этот параметр появился в PowerShell 7.0.
Тип: | ScriptBlock |
Position: | Named |
Default value: | None |
Обязательно: | True |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-Process
Указывает операцию, выполняемую для каждого входного объекта. Этот блок скрипта выполняется для каждого объекта в конвейере. Дополнительные сведения о блоке process
см. в about_Functions.
При предоставлении нескольких блоков скриптов параметру процесса первый блок скрипта всегда сопоставляется с блоком begin
. Если существует только два блока скриптов, второй блок сопоставляется с блоком process
. Если существует три или более блоков скриптов, первый блок скрипта всегда сопоставляется с блоком begin
, последний блок сопоставляется с блоком end
, а средние блоки сопоставляются с блоком process
.
Тип: | ScriptBlock[] |
Position: | 0 |
Default value: | None |
Обязательно: | True |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-RemainingScripts
Указывает все блоки скриптов, которые не принимаются параметром процесса.
Этот параметр появился в Windows PowerShell 3.0.
Тип: | ScriptBlock[] |
Position: | Named |
Default value: | None |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-ThrottleLimit
Указывает количество блоков скриптов, выполняемых параллельно. Входные объекты блокируются до тех пор, пока число блоков скрипта не будет ниже ThrottleLimit. Значение по умолчанию — 5
.
Параметр ThrottleLimit ограничивает количество параллельных скриптов, выполняемых во время каждого экземпляра ForEach-Object -Parallel
. Это не ограничивает количество заданий, которые можно создать при использовании параметра AsJob. Так как задания выполняются одновременно, можно создать ряд параллельных заданий, каждое из которых выполняется до ограничения числа одновременных блокировок скриптов.
Этот параметр появился в PowerShell 7.0.
Тип: | Int32 |
Position: | Named |
Default value: | 5 |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-TimeoutSeconds
Указывает количество секунд, ожидающее параллельной обработки всех входных данных. После указанного времени ожидания все выполняемые скрипты будут остановлены. И все остальные входные объекты, которые будут обработаны, игнорируются. Значение по умолчанию 0
отключает время ожидания и ForEach-Object -Parallel
может выполняться неограниченное время ожидания. Ввод ctrl+C в командной строке останавливает выполнение команды ForEach-Object -Parallel
. Этот параметр нельзя использовать вместе с параметром AsJob.
Этот параметр появился в PowerShell 7.0.
Тип: | Int32 |
Position: | Named |
Default value: | 0 |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-UseNewRunspace
Вызывает параллельное вызов для создания нового пространства выполнения для каждой итерации цикла вместо повторного использования пространств выполнения из пула пространств runspace.
Этот параметр появился в PowerShell 7.1
Тип: | SwitchParameter |
Position: | Named |
Default value: | False |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-WhatIf
Показывает, что произойдет, если командлет выполняется. Командлет не выполняется.
Тип: | SwitchParameter |
Aliases: | wi |
Position: | Named |
Default value: | False |
Обязательно: | False |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
Входные данные
Вы можете передать любой объект в этот командлет.
Выходные данные
Этот командлет возвращает объекты, определяемые входными данными.
Примечания
PowerShell включает следующие псевдонимы для ForEach-Object
:
- Все платформы:
%
foreach
Командлет ForEach-Object
работает так же, как оператор Foreach, за исключением того, что входные данные foreach невозможно передать. Дополнительные сведения об инструкции foreach см. в about_Foreach.
Начиная с PowerShell 4.0, были добавлены методы Where
и ForEach
для использования с коллекциями. Дополнительные сведения об этих новых методах см. здесь about_arrays
Использование ForEach-Object -Parallel
:
ForEach-Object -Parallel
выполняет каждый блок скрипта в новом пространстве выполнения. Новые пространства выполнения создают значительно больше затрат, чем выполнениеForEach-Object
с последовательной обработкой. Важно использовать параллельных, когда затраты на выполнение параллельного выполнения небольшие по сравнению с работой блока скрипта выполняются. Например:- Вычислительные интенсивные скрипты на нескольких ядрах компьютеров
- Скрипты, которые тратят время на ожидание результатов или выполнение операций с файлами
Использование параметра Parallel может привести к тому, что скрипты выполняются гораздо медленнее, чем обычно. Особенно если параллельные скрипты являются тривиальными. Поэкспериментируйте с параллельных, чтобы узнать, где это может быть полезно.
При параллельном выполнении объектов, украшенных ScriptProperties или ScriptMethods, невозможно обеспечить правильную работу, если они выполняются в другом пространстве выполнения, чем скрипты изначально присоединены к ним.
Вызов scriptblock всегда пытается запуститься в своем домашнем пространстве выполнения независимо от того, где он на самом деле вызывается. Однако
ForEach-Object -Parallel
создает временные пространства выполнения, которые удаляются после использования, поэтому в скриптах больше нет пространства выполнения.Это поведение может работать до тех пор, пока домашнее пространство выполнения по-прежнему существует. Однако вы можете не получить нужный результат, если скрипт зависит от внешних переменных, которые присутствуют только в пространстве выполнения вызывающего средства, а не в домашнем пространстве выполнения.
Несрочные ошибки записываются в поток ошибок командлета, так как они происходят параллельно с запущенными блоками скриптов. Так как порядок выполнения параллельного скрипта не детерминирован, порядок отображения ошибок в потоке ошибок является случайным. Аналогичным образом сообщения, записанные в другие потоки данных, такие как предупреждение, подробные сведения или данные записываются в эти потоки данных в неопределенном порядке.
Завершающие ошибки, такие как исключения, завершают отдельный параллельный экземпляр скриптов, в котором они происходят. Завершающая ошибка в одном блоке скриптов может не вызвать завершение командлета
Foreach-Object
. Другие блоки скриптов, выполняемые параллельно, продолжают выполняться, если они также не сталкиваются с завершающейся ошибкой. Завершающая ошибка записывается в поток данных об ошибке в виде errorRecord с ПолнофункциональныйErrorIdPSTaskException
. Завершающие ошибки можно преобразовать в неустранимые ошибки с помощьюtry
/catch
PowerShell или блоковtrap
.PipelineVariable общие переменные параметров не поддерживаются в параллельных сценариях даже с ключевым словом
$using:
.Важный
Набор параметров
ForEach-Object -Parallel
выполняет блоки скриптов параллельно в отдельных потоках процессов. Ключевое слово$using:
позволяет передавать ссылки на переменные из потока вызова командлета в каждый запущенный поток блока скрипта. Так как блоки скриптов выполняются в разных потоках, переменные объекта, передаваемые по ссылке, должны использоваться безопасно. Как правило, это безопасно для чтения из ссылочных объектов, которые не изменяются. Если необходимо изменить состояние объекта, необходимо использовать потокобезопасные объекты, такие как .NET System.Collection.Concurrent (см. пример 14).
Связанные ссылки
PowerShell