Примечание. Этот ответ не охватывает PowerShell рабочие процессы , поскольку они являются устаревшей технологией, более не поддерживаемой в PowerShell [Core] v6 + - см. этот блог post .
Для всего, что выполняется вне пространства выполнения, то есть не выполняется непосредственно в пространстве выполнения вызывающей стороны (поток), вам нужен $using:
scope для встраивания переменной значения [1] из области действия вызывающего абонента , так что выход из пространства выполнения может получить к нему доступ. (И наоборот, все другие контексты не требуют и не поддерживают $using:
)
Примечание. На момент написания этой статьи в связанной справке topi c отсутствуют важные аспекты того, что это Ответ резюмирует. Несколько ошибок GitHub были открыты, чтобы исправить это.
В частности, это включает следующие контексты:
Удаленно выполняемые команды , началось с Invoke-Command
-ComputerName
.
Runspace-local использование Invoke-Command
- что и происходит без -ComputerName
- не требует и не поддерживает ссылки $using:
(он запускается в дочерней области области действия вызывающей стороны или, с -NoNewScope
, непосредственно в области действия вызывающей стороны).
- Использование локального пространства выполнения
Invoke-Command
редко требуется, поскольку оператор &
, call (execute) (выполнение в дочерней области) и .
, (точка-) оператор источника (выполнение непосредственно в области действия вызывающего), являются более лаконичными и эффективными альтернативами.
Обратите внимание, что если вы используйте параметр -ComputerName
для целевого компьютера local , команда по-прежнему обрабатывается так, как если бы это было n, т. е. он проходит через инфраструктуру удаленного взаимодействия PowerShell, и применяются те же правила, что и для истинного удаленного выполнения.
Фоновые задания , запущено с Start-Job
Работы с нитями , запущенные с помощью Start-ThreadJob
.
- В PowerShell [Core] v7 + это также включает блоки сценариев, передаваемые в
ForEach-Object
с переключателем -Parallel
.
Дистанционно выполняемые команды и фоновые задания запускаются вне процесса [2] , а для значений, пересекающих эти границы процесса, они под go XML сериализация и десериализация на основе , которая обычно включает потерю точности типа - как на входе, так и на выходе.
См. this Ответьте для справочной информации.
Обратите внимание, что это относится не только к значениям, встроенным в $using:
, но и к значениям, передаваемым как argum вводит через параметр -ArgumentList
(-Args
) в Invoke-Command [-ComputerName]
и Start-Job
.
Задания потоков , напротив, потому что они запускать в другом пространстве выполнения (потоке) в том же процессе , получать $using:
значения переменных в качестве своих исходных, живых объектов и, аналогично, возвращать такие объекты.
Предупреждение заключается в том, что может потребоваться явная синхронизация между пространствами выполнения (потоками) , если все они обращаются к данному изменяемому экземпляру ссылочного типа - который наиболее может произойти с ForEach-Object -Parallel
.
Как правило, задания потоков в большинстве случаев являются лучшей альтернативой фоновым заданиям благодаря их значительно лучшей производительности, меньшему использованию ресурсов и точности типов.
[1] Обратите внимание, что это означает, что код внеполосного пространства никогда не может изменять переменные в области действия вызывающего . Однако в случае потоков заданий (но не во время удаленного взаимодействия и не в фоновых заданиях), если переменная значение оказывается экземпляром ссылочного типа (например (тип коллекции), можно изменить этот экземпляр в другом потоке, что требует синхронизации изменений между потоками, если несколько потоков выполнят изменения.
[ 2] В отличие от удаленных команд, фоновые задания выполняются на том же компьютере , но в (скрытом) PowerShell дочернем процессе .