PowerShell中当ThreadJob有新数据时异步触发函数的实现方案
解决ThreadJob有新数据时触发函数的方案
方案1:轮询检测HasMoreData(最简单直接)
不用修改原作业逻辑,靠后台轮询作业的HasMoreData属性,一旦为True就调用目标函数。
# 启动你的线程作业 $threadJob = Start-ThreadJob { foreach ($i in 1..5) { Write-Output "新内容 $i" Start-Sleep 2 # 模拟耗时任务 } } # 定义要触发的函数 function OnNewData { param($job) Write-Host "作业[$($job.Id)]有新数据:" Receive-Job $job # 取出数据,避免重复触发 } # 启动轮询的后台作业 Start-ThreadJob { param($targetJob, $triggerFunc) # 作业没结束就持续检测 while ($targetJob.State -notin 'Completed', 'Failed', 'Stopped') { if ($targetJob.HasMoreData) { & $triggerFunc $targetJob } Start-Sleep 1 # 调整间隔,平衡响应速度和性能 } # 作业结束后检查最后一批数据 if ($targetJob.HasMoreData) { & $triggerFunc $targetJob } } -ArgumentList $threadJob, ${function:OnNewData}
方案2:作业主动触发事件(实时性更好)
让线程作业在产生输出时直接触发自定义事件,主进程监听这个事件即可,没有轮询延迟。
# 自定义事件标识 $newDataEvent = "ThreadJob_NewData" # 注册事件处理函数 Register-EngineEvent -SourceIdentifier $newDataEvent -Action { param($jobId, $data) Write-Host "作业[$jobId]刚输出:$data" } # 启动线程作业,输出时主动发事件 $threadJob = Start-ThreadJob { param($eventName) foreach ($i in 1..5) { $output = "实时输出 $i" Write-Output $output # 触发事件,传递作业ID和数据 New-Event -SourceIdentifier $eventName -MessageData @($using:threadJob.Id, $output) Start-Sleep 2 } } -ArgumentList $newDataEvent # 作业结束后清理事件 Wait-Job $threadJob Unregister-Event -SourceIdentifier $newDataEvent
方案3:监听作业输出流(不修改原作业)
如果不想改动原作业的脚本,可以直接监听作业的内部输出流,有新数据就读取并触发函数。
# 启动原线程作业 $threadJob = Start-ThreadJob { foreach ($i in 1..5) { Write-Output "流输出 $i" Start-Sleep 2 } } # 定义处理函数 function ProcessNewOutput { param($output) Write-Host "捕获到新输出:$output" } # 启动线程持续读取输出流 Start-ThreadJob { param($job, $handler) while ($job.State -notin 'Completed', 'Failed', 'Stopped') { $output = $job.ChildJobs[0].Output.ReadToEnd() if ($output) { & $handler $output } Start-Sleep 0.5 } # 读取剩余输出 if ($output = $job.ChildJobs[0].Output.ReadToEnd()) { & $handler $output } } -ArgumentList $threadJob, ${function:ProcessNewOutput}
内容的提问来源于stack exchange,提问作者Maybe
相关产品推荐
相关产品推荐

