很奇怪,我又改了两版,暂时不能复现了,其中之一应该是之前的问题代码,但当时没保存,除了Job类忘了改过哪了。
1、这版添了几行输出就没再死锁?!- class Job {
- Init() {
- $this.ps.Streams.Information.add_DataAdded( {
- Param ( [Object]$sender, [System.Management.Automation.DataAddedEventArgs]$e )
- $i=0
- while(!($all = $sender.ReadAll())) {$i++;Write-Warning [Information] ReadAll阻塞:$i;Start-Sleep -Milliseconds 10}
- foreach($o in $all) { Write-Host $o }
- })
-
- }
-
- }
复制代码 2、这是之前的版本,当时出死锁问题,- class Job {
- Init() {
- $this.ps.Streams.Information.add_DataAdded( {
- Param ( [Object]$sender, [System.Management.Automation.DataAddedEventArgs]$e )
- foreach($o in $sender.ReadAll()) { Write-Host $o }
- })
- }
-
- }
复制代码 在官网查到
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- cls
- # 处理任务
- $Worker = {
- param($Filename)
- $i=0
- Write-Host "Processing $filename"
- $i=1
- #[Threading.Thread]::Sleep(100)
- Start-Sleep -Seconds 1 # Doing some work....
- $i=2
- Write-Host "Processed $filename"
- $i=3
- }
- # 最大并发
- $MaxRunspaces = 10
-
- try {
- # 线程池
- $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxRunspaces)
- $RunspacePool.Open()
-
- $Filenames = @("file1.txt", "file2.txt", "file3.txt", "file4.txt", "file5.txt", "file6.txt", "file7.txt", "file8.txt", "file9.txt", "file10.txt", "file11.txt")
-
- while($true) {
- # 开始时间
- $StartTime = Get-Date
- $Jobs = New-Object System.Collections.ArrayList
-
- foreach ($File in $Filenames) {
- Write-Host "Creating runspace for $File"
- $job=[Job]::new($RunspacePool)
- $null=$job.GetPowerShell().AddScript($Worker).AddArgument($File)
- $null=$Jobs.Add($job)
- $job.Run()
- }
-
- while ($Jobs.IsCompleted() -contains $false) {
- Write-Host (Get-date).Tostring() "Still running..."
- #[Threading.Thread]::Sleep(1000)
- Start-Sleep 1
- $Jobs.IsCompleted()
- }
- # 结束时间
- $endTime = Get-Date
- # 运行时间
- Write-Host "The script runs for Total time (s):$(($endTime - $StartTime).TotalSeconds)"
- # 任务对象信息
- $Jobs.GetPowerShell().Streams.Information
- $Jobs.GetPowerShell().haderrors
- $c=Read-Host '输入e退出'
- if($c -eq 'e') {break}
- }
- }
- finally {
- # 始终关闭进程池
- $RunspacePool.Close()
- }
-
-
- class Job {
- hidden [powershell]$ps = [powershell]::Create()
- hidden [IAsyncResult]$result
-
- Job([System.Management.Automation.Runspaces.RunspacePool]$runspacepool) {
- $this.ps.RunspacePool = $runspacepool
- $this.Init()
- }
-
- Init() {
- $this.ps.Streams.Information.add_DataAdded( {
- Param ( [Object]$sender, [System.Management.Automation.DataAddedEventArgs]$e )
- while(!($all = $sender.ReadAll())) {Start-Sleep -Milliseconds 10}
- foreach($o in $all) { Write-Host $o }
- })
- }
-
- [powershell] GetPowerShell() {
- return $this.ps
- }
-
- [IAsyncResult] GetResult() {
- return $this.result
- }
-
- [bool]IsCompleted() {
- return $this.result.IsCompleted
- }
-
- [IAsyncResult] Run() {
- return $this.result = $this.ps.BeginInvoke()
- }
- }
复制代码
|