PowerShell中的异步处理与事件响应
立即解锁
发布时间: 2025-08-14 00:54:57 阅读量: 20 订阅数: 29 AIGC 


精通PowerShell脚本编写:自动化与简化任务
### PowerShell 中的异步处理与事件响应
#### 1. 启动作业
在 PowerShell 中,有多种方式可以将命令放入作业中执行。例如,使用 `Get-Process &` 可以将 `Get-Process` 命令放入后台作业执行,这等价于使用 `Start-Job -ScriptBlock { Get-Process }` 命令。
```powershell
Get-Process &
Start-Job -ScriptBlock { Get-Process }
```
无论是使用后台操作符 `&` 还是 `Start-Job` 命令,作业都会在当前 PowerShell 工作目录中启动。当使用 `Start-Job` 时,工作目录会隐式继承自启动作业的会话;而使用后台操作符时,工作目录会被显式设置。
```powershell
PS> $job = Get-Process &
PS> $job.Command
Microsoft.PowerShell.Management\Set-Location -LiteralPath $using:pwd ; Get-Process
```
#### 2. ThreadJob 模块
PowerShell 7 附带了 `ThreadJob` 模块,`Start-ThreadJob` 提供了比 `Start-Job` 更快的替代方案。它利用 PowerShell 运行空间来执行脚本。
```powershell
Start-ThreadJob { Write-Host 'Hello world' } | Receive-Job -Wait
```
`Start-ThreadJob` 命令允许用户定义一个初始化脚本,该脚本会在运行空间中其他命令开始之前运行。不过,初始化脚本目前不能使用 `using` 作用域修饰符。
#### 3. 批量作业
在处理作业时,需要考虑作业的构成。如果任务是使用 `Invoke-Command` 在 100 个远程主机上运行单个命令,那么允许 100 个作业同时运行可能不会有太大问题。但如果任务是本地的,并且需要访问本地资源(如 CPU 或磁盘),则可能更适合运行较少数量的作业,通常与可用核心数一致。
对于需要处理大量对象的情况,可以使用循环或 Linq 的 `Chunk` 方法来创建批量作业。
```powershell
# 使用 for 循环创建批量作业
$objects = foreach ($value in 1..1000) {
[PSCustomObject]@{ Value = $value }
}
$batchSize = 100
$ScriptBlock = {
# Long job set-up step
Start-Sleep -Seconds 120
foreach ($object in $using:batch) {
# Perform action and create output
$object
}
}
for ($i = 0; $i -lt $objects.Count; $i += $batchSize) {
$batch = $objects[$i..($i + $batchSize)]
Start-Job -ScriptBlock $ScriptBlock
}
# 使用 Linq 的 Chunk 方法创建批量作业
using namespace System.Linq
$objects = foreach ($value in 1..1000) {
[PSCustomObject]@{ Value = $value }
}
$batchSize = 100
$ScriptBlock = {
# Long job set-up step
Start-Sleep -Seconds 120
foreach ($object in $using:batch) {
# Perform action and create output
$object
}
}
$batches = [Enumerable]::Chunk[object]($objects, $batchSize)
foreach ($batch in $batches) {
Start-Job -ScriptBlock $ScriptBlock
}
```
#### 4. 响应事件
在 .NET 中,当对象发生感兴趣的事情时会触发事件。例如,`System.IO.FileSystemWatcher` 可以用于监视文件系统的更改,当发生更改时会引发事件。
```powershell
PS> Get-Process | Get-Member -MemberType Event
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Disposed Event System.EventHandler Disposed(Syst...
ErrorDataReceived Event System.Diagnostics.DataReceivedEv...
Exited Event System.EventHandler Exited(System...
OutputDataReceived Event System.Diagnostics.DataReceivedEv...
```
PowerShell 可以对这些事件做出响应,在事件发生时执行代码。以 `FileSystemWatcher` 为例,它可以响应多种不同的事件,如 `Changed`、`Created`、`Deleted` 等。
```powershell
$watcher = [System.IO.FileSystemWatcher]::new('C:\Data')
Register-ObjectEvent -InputObject $watcher -EventName Changed
Register-ObjectEvent -InputObject $watcher -EventName Created
```
使用 `Register-ObjectEvent` 命令可以注册对 .NET 对象引发的事件的兴趣,该命令会创建一个 `PSEventSubscriber` 对象。
#### 5. 事件处理
当文件系统发生更改时,会引发相应的事件。可以使用 `Get-Event` 命令查看事件数据。
```powershell
PS> New-Item C:\Data\new.txt | Out-Null
PS> Get-Event
ComputerName :
RunspaceId : 46d2a562-2d07-4c58-9416-f82a3e9da5b8
EventIdentifier : 3
Sender : System.IO.FileSystemWatcher
SourceEventArgs : System.IO.FileSystemEventArgs
SourceArgs : {System.IO.FileSystemWatcher, new.txt}
SourceIdentifier : ff0784dc-1f0f-4214-b5e7-5d5516eaa13e
TimeGenerated : 19/02/2019 17:29:53
MessageData :
```
事件会一直存在,直到使用 `Remove-Eve
0
0
复制全文
相关推荐









