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
.
Синтаксис блока скрипта. Чтобы указать операцию, можно использовать блок скрипта. В блоке скрипта используйте переменную
$_
для представления текущего объекта. Блок скрипта — это значение параметра Process . Блок скрипта может содержать любой скрипт PowerShell.Например, следующая команда получает значение свойства ProcessName каждого процесса на компьютере.
Get-Process | ForEach-Object {$_.ProcessName}
ForEach-Object
поддерживает блоки иbegin
process
блокиend
, как описано в about_Functions.Замечание
Блоки скрипта выполняются в области вызывающего абонента. Поэтому блоки имеют доступ к переменным в этой области и могут создавать новые переменные, которые сохраняются в этой области после завершения командлета.
Упрощенный синтаксис. Используя упрощенный синтаксис, вы указываете свойство или имя метода объекта в конвейере.
ForEach-Object
возвращает значение свойства или метода для каждого объекта в конвейере.Например, следующая команда также получает значение свойства ProcessName каждого процесса на компьютере.
Get-Process | ForEach-Object ProcessName
Упрощенный синтаксис появился в Windows PowerShell 3.0. Дополнительные сведения см. в about_Simplified_Syntax.
Параллельный блок скриптов параллельного выполнения. Начиная с 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 отображает текущую дату и время. Затем параметр Process использует 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 со значением реестра 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
полезен для получения значений свойств, так как он получает значение без изменения типа, в отличие от командлетов Format или 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 с двумя блоками скриптов
В этом примере мы передаваем два блока скрипта позиционально. Все блоки скрипта привязываются к параметру Process . Однако они обрабатываются так, как если бы они были переданы параметрам Begin и Process .
1..2 | ForEach-Object { 'begin' } { 'process' }
begin
process
process
Пример 9. Использование ForEach-Object с более чем двумя блоками скриптов
В этом примере мы передаваем четыре блока скрипта позиционально. Все блоки скрипта привязываются к параметру Process . Однако они обрабатываются так, как если бы они были переданы в параметры 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. Запуск нескольких блоков скриптов для каждого элемента конвейера
Как показано в предыдущем примере, несколько блоков скриптов, переданных с помощью параметра Process , сопоставляются с параметрами 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. Передача переменных в вложенных параллельных скриптах
Вы можете создать переменную за пределами ForEach-Object -Parallel
области скрипта и использовать ее внутри скриптблока с модификатором Using:
области. Начиная с PowerShell 7.2, можно создать переменную внутри области скрипта и использовать ее в ForEach-Object -Parallel
вложенном блоке скрипта.
$test1 = 'TestA'
1..2 | ForEach-Object -Parallel {
$Using:test1
$test2 = 'TestB'
1..2 | ForEach-Object -Parallel {
$Using:test2
}
}
TestA
TestA
TestB
TestB
TestB
TestB
Замечание
В версиях до PowerShell 7.2 вложенный блок скриптов не может получить доступ к переменной $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
Запрашивает подтверждение перед запуском cmdlet.
Тип: | 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.
При предоставлении нескольких блоков скриптов параметру Process первый блок скрипта всегда сопоставляется с блоком begin
. Если существует только два блока скриптов, второй блок сопоставляется с блоком process
. Если существует три или более блоков скриптов, первый блок скрипта всегда сопоставляется с блоком begin
, последний блок сопоставляется с блоком end
, а средние блоки сопоставляются с блоком process
.
Тип: | ScriptBlock[] |
Position: | 0 |
Default value: | None |
Обязательно: | True |
Принять входные данные конвейера: | False |
Принять подстановочные знаки: | False |
-RemainingScripts
Указывает все блоки скриптов, которые не принимаются параметром Process .
Этот параметр появился в 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 |
Входные данные
Вы можете передать любой объект в этот cmdlet.
Выходные данные
Этот командлет возвращает объекты, определяемые входными данными.
Примечания
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 , когда затраты на выполнение параллельно небольшие по сравнению с работой блока скрипта выполняются. Рассмотрим пример.- Вычислительные интенсивные скрипты на нескольких ядрах компьютеров
- Скрипты, которые тратят время на ожидание результатов или выполнение операций с файлами
Использование параметра Parallel может привести к тому, что скрипты выполняются гораздо медленнее, чем обычно. Особенно если параллельные скрипты являются тривиальными. Поэкспериментируйте с Parallel , чтобы узнать, где это может быть полезно.
При параллельном выполнении объектов, украшенных scriptProperties или ScriptMethods , невозможно обеспечить правильную работу, если они выполняются в другом пространстве выполнения, чем скрипты изначально присоединены к ним.
Вызов scriptblock всегда пытается выполняться в своем домашнем пространстве выполнения независимо от того, где он фактически вызывается.
ForEach-Object -Parallel
Однако создает временные пространства выполнения, которые удаляются после использования, поэтому больше нет пространства выполнения скриптов.Это поведение может работать до тех пор, пока домашнее пространство выполнения по-прежнему существует. Однако вы можете не получить нужный результат, если скрипт зависит от внешних переменных, которые присутствуют только в пространстве выполнения вызывающего средства, а не на домашнем пространстве выполнения.
Несрочные ошибки записываются в поток ошибок командлета, так как они происходят параллельно с запущенными блоками скриптов. Так как порядок выполнения параллельного скрипта не детерминирован, порядок отображения ошибок в потоке ошибок является случайным. Аналогичным образом сообщения, записанные в другие потоки данных, такие как предупреждение, подробные сведения или данные записываются в эти потоки данных в неопределенном порядке.
Завершающие ошибки, такие как исключения, завершают отдельный параллельный экземпляр скриптов, в котором они происходят. Завершающая ошибка в одном блоке скриптов может не вызвать завершение командлета
ForEach-Object
. Другие блоки скриптов, выполняемые параллельно, продолжают выполняться, если они также не сталкиваются с завершающейся ошибкой. Завершающая ошибка записывается в поток данных об ошибках в виде errorRecord с полнофункциональнымErrorIdPSTaskException
. Завершающие ошибки можно преобразовать в неисключающие ошибки с помощью PowerShelltry
/catch
илиtrap
блоков.Общие переменные параметров PipelineVariableне поддерживаются в параллельных сценариях даже с модификатором
Using:
области.Это важно
Набор
ForEach-Object -Parallel
параметров выполняет блоки скриптов параллельно в отдельных потоках процесса. МодификаторUsing:
позволяет передавать ссылки на переменные из потока вызова командлета в каждый запущенный поток блока скрипта. Так как блоки скриптов выполняются в разных потоках, переменные объекта, передаваемые по ссылке, должны использоваться безопасно. Как правило, это безопасно для чтения из ссылочных объектов, которые не изменяются. Если необходимо изменить состояние объекта, необходимо использовать потокобезопасные объекты, такие как .NET System.Collection.Concurrent (см. пример 14).