[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] PowerShell多线程runspace怎么输出到控制台?

很奇怪,我又改了两版,暂时不能复现了,其中之一应该是之前的问题代码,但当时没保存,除了Job类忘了改过哪了。
1、这版添了几行输出就没再死锁?!
  1. class Job {
  2.     Init() {
  3.         $this.ps.Streams.Information.add_DataAdded( {
  4.             Param ( [Object]$sender, [System.Management.Automation.DataAddedEventArgs]$e )
  5.     $i=0
  6.             while(!($all = $sender.ReadAll())) {$i++;Write-Warning [Information] ReadAll阻塞:$i;Start-Sleep -Milliseconds 10}
  7.             foreach($o in $all) { Write-Host $o }
  8.         })
  9.     }
  10. }
复制代码
2、这是之前的版本,当时出死锁问题,
  1. class Job {
  2.     Init() {
  3.         $this.ps.Streams.Information.add_DataAdded( {
  4.             Param ( [Object]$sender, [System.Management.Automation.DataAddedEventArgs]$e )
  5.             foreach($o in $sender.ReadAll()) { Write-Host $o }
  6.         })
  7.     }
  8. }
复制代码
在官网查到
https://learn.microsoft.com/zh-c ... powershellsdk-1.1.0
我理解是遇到阻塞返回空,就添加了while代码


原问题:
想实现多线程,搜到推荐runspace,试了试AI给的代码,只能运行完才能看输出,
搜到一种方法,自己改了改,虽然能实时看到输出了,但是大概率会出现线程代码不返回,
怀疑是多线程死锁,但是没有能力调试和解决,请大神帮忙看看,先谢了!

1、注释71行代码,就不能实时输出了,但是不会死锁。。。
2、偶尔还出现过报错:
不能对 Null 值表达式调用方法。
所在位置 :56 字符: 5
+     $RunspacePool.Close()

所在位置 :37 字符: 16
+         while ($Jobs.IsCompleted() -contains $false) {
+                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: ( [],RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
  1. cls
  2. # 处理任务
  3. $Worker = {
  4.     param($Filename)
  5.     $i=0
  6.     Write-Host "Processing $filename"
  7.     $i=1
  8.     #[Threading.Thread]::Sleep(100)
  9.     Start-Sleep -Seconds 1 # Doing some work....
  10.     $i=2
  11.     Write-Host "Processed $filename"
  12.     $i=3
  13. }
  14. # 最大并发
  15. $MaxRunspaces = 10
  16. try {
  17. # 线程池
  18.     $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxRunspaces)
  19.     $RunspacePool.Open()
  20.     $Filenames = @("file1.txt", "file2.txt", "file3.txt", "file4.txt", "file5.txt", "file6.txt", "file7.txt", "file8.txt", "file9.txt", "file10.txt", "file11.txt")
  21.     while($true) {
  22.         # 开始时间
  23.         $StartTime = Get-Date
  24.         $Jobs = New-Object System.Collections.ArrayList
  25.         foreach ($File in $Filenames) {
  26.             Write-Host "Creating runspace for $File"
  27.             $job=[Job]::new($RunspacePool)
  28.             $null=$job.GetPowerShell().AddScript($Worker).AddArgument($File)
  29.             $null=$Jobs.Add($job)
  30.             $job.Run()
  31.         }
  32.         while ($Jobs.IsCompleted() -contains $false) {
  33.             Write-Host (Get-date).Tostring() "Still running..."
  34.             #[Threading.Thread]::Sleep(1000)
  35.             Start-Sleep 1
  36.             $Jobs.IsCompleted()
  37.         }
  38.         # 结束时间
  39.         $endTime = Get-Date
  40.         # 运行时间
  41.         Write-Host "The script runs for Total time (s):$(($endTime - $StartTime).TotalSeconds)"
  42.         # 任务对象信息
  43.         $Jobs.GetPowerShell().Streams.Information
  44.         $Jobs.GetPowerShell().haderrors
  45.         $c=Read-Host '输入e退出'
  46.         if($c -eq 'e') {break}
  47.     }
  48. }
  49. finally {
  50. # 始终关闭进程池
  51.     $RunspacePool.Close()
  52. }
  53. class Job {
  54.     hidden [powershell]$ps = [powershell]::Create()
  55.     hidden [IAsyncResult]$result
  56.    
  57.     Job([System.Management.Automation.Runspaces.RunspacePool]$runspacepool) {
  58.         $this.ps.RunspacePool = $runspacepool
  59.         $this.Init()
  60.     }
  61.     Init() {
  62.         $this.ps.Streams.Information.add_DataAdded( {
  63.             Param ( [Object]$sender, [System.Management.Automation.DataAddedEventArgs]$e )
  64.             while(!($all = $sender.ReadAll())) {Start-Sleep -Milliseconds 10}
  65.             foreach($o in $all) { Write-Host $o }
  66.         })
  67.     }
  68.     [powershell] GetPowerShell() {
  69.         return $this.ps
  70.     }
  71.    
  72.     [IAsyncResult] GetResult() {
  73.         return $this.result
  74.     }
  75.     [bool]IsCompleted() {
  76.         return $this.result.IsCompleted
  77.     }
  78.     [IAsyncResult] Run() {
  79.         return $this.result = $this.ps.BeginInvoke()
  80.     }
  81. }
复制代码

回复 2# flashercs


    非常感谢!使用Win10自带应该是5.1,目前还在试验多线程就遇到不少问题,预想的功能还没添加。
我原想是控制台输入路径,开一个主线程读取文件,然后将字符串共享给多个处理线程,
然后主线程继续读取下一个文件,处理线程将结果输出到控制台。
不知workflow能实现吗

TOP

返回列表