如何让PowerShell中基于Task的Async调用生成可用事件?有无替代工具?
处理PowerShell中基于Task的异步操作事件
不用强行将Task转换为IAsyncResult,直接利用Task的延续机制结合PowerShell原生事件系统,就能实现类似New-ScriptblockCallback的功能,让Task异步调用完成时触发可便捷使用的PowerShell事件。
自定义辅助函数
可以封装一个专门的辅助函数,用来生成Task完成时的回调,自动触发指定事件:
function New-TaskEventCallback { param( [Parameter(Mandatory)] [string]$EventName, [Parameter(Mandatory)] [scriptblock]$EventDataProcessor ) return { param($task) if ($task.IsCompleted) { $eventData = if ($EventDataProcessor) { & $EventDataProcessor $task } else { $task } New-Event -SourceIdentifier $EventName -MessageData $eventData } }.GetNewClosure() }
函数说明
EventName:指定Task完成时要触发的PowerShell事件名称EventDataProcessor:可选脚本块,用于处理Task的结果(如提取状态、异常、关联对象等),生成最终传递给事件的自定义数据- 返回的委托可直接绑定到Task的
ContinueWith方法,Task完成后自动触发事件
使用示例(以ClientWebSocket为例)
# 1. 定义事件处理逻辑 $onWebSocketConnected = { param($sender, $eventArgs) $eventData = $eventArgs.MessageData if ($eventData.Status -eq 'RanToCompletion') { Write-Host "WebSocket连接成功" # 这里可添加后续操作,比如发送测试消息 $sendTask = $eventData.WebSocket.SendAsync( [System.ArraySegment[byte]][System.Text.Encoding]::UTF8.GetBytes("Hello WebSocket"), [System.Net.WebSockets.WebSocketMessageType]::Text, $true, [System.Threading.CancellationToken]::None ) # 可继续绑定SendAsync的完成事件 $sendCallback = New-TaskEventCallback -EventName "WebSocket.MessageSent" -EventDataProcessor { $_ } $sendTask.ContinueWith($sendCallback) } else { Write-Host "WebSocket连接失败:$($eventData.Exception.Message)" } } # 2. 注册事件 Register-EngineEvent -SourceIdentifier "WebSocket.Connected" -Action $onWebSocketConnected Register-EngineEvent -SourceIdentifier "WebSocket.MessageSent" -Action { Write-Host "消息发送完成,任务状态:$($args[1].MessageData.Status)" } # 3. 发起异步WebSocket连接 $ws = [System.Net.WebSockets.ClientWebSocket]::new() $connectTask = $ws.ConnectAsync([Uri]"wss://echo.websocket.org", [System.Threading.CancellationToken]::None) # 4. 绑定Task完成回调 $callback = New-TaskEventCallback -EventName "WebSocket.Connected" -EventDataProcessor { param($task) return @{ Status = $task.Status WebSocket = $ws Exception = $task.Exception } } $connectTask.ContinueWith($callback)
关键注意事项
- 完全基于Task异步API,符合微软弃用Begin/End模型后的推荐方向
- 触发的事件可与PowerShell原生事件(如
Register-ObjectEvent注册的事件)无缝混合使用 - 可在
EventDataProcessor中灵活处理Task的结果、异常等信息,按需传递给事件处理逻辑
内容的提问来源于stack exchange,提问作者Alain
相关产品推荐
相关产品推荐

