更新
此解决方案允许在后台作业运行时在UI线程中获取更新,但它不能保持UI响应。看我的
对罗欣的回应如下。
解决方法是将整个循环移动到
background job
Write-Progress
cmdlet来报告
UI
. 使用
写入进度
此场景中的cmdlet转到
Ryan
这里是一个简单的演示说明所有需要的部分
cls
## Job code
$ScriptBlockCode =
{
param($items)
$retObj = @{}
try
{
$error.clear()
for ($i = 0; $i -lt $items.Count; $i++)
{
#wait to simulate the time it takes to do work on item $i
start-sleep -Seconds (get-random -Minimum 2 -Maximum 6)
# Use Write-Progress to report the completion of each item for as long as the job runs (Can be used to updage the UI)
# Use the -Completed argument to suppress displaying the progress bar
Write-Progress -Id ($i+1) -Activity ("For UI Update: " + $items[$i] + " processing complete") -Status "Reporting" -PercentComplete ((($i+1)/$items.Count)*100) -Completed
#Use a hashtable to report the status of each job. To be used in the calling code after the job status is no longer Running
#simulate some items passing, some failing
if ((get-random -Minimum 0 -Maximum 2) -eq 0)
{
$itemRet = [PSCustomObject]@{status="FAIL";details="some error description"}
}
else
{
$itemRet = [PSCustomObject]@{status="PASS";details=""}
}
$retObj.Add($items[$i],$itemRet)
}
return $retObj
}
catch
{
$itemRet = [PSCustomObject]@{status="ERROR";details=$error}
$retObj.Add("FATAL",$itemRet)
return $retObj
}
}
cls
#clean up before starting
Get-Job -Name "UniqueJobName" -ErrorAction SilentlyContinue | Stop-Job
Get-Job -Name "UniqueJobName" -ErrorAction SilentlyContinue | Remove-Job
#simulate 5 pieces of work
$items = @("Item A", "Item B", "Item C", "Item D", "Item E")
$job = Start-Job -Name "UniqueJobName" -ScriptBlock $ScriptBlockCode -ArgumentList ($items)
#loop and update UI until job is done
$lastActivityId = -99
While ($job.State -eq "Running")
{
$child = $job.ChildJobs[0]
#update the UI only if progress has started and the ActivityId has not already been reported on and the Progress report is one I care about
if ($child.Progress.Count -gt 0 -and $child.Progress[$child.Progress.Count - 1].ActivityId -ne $lastActivityId -and ($child.Progress[$child.Progress.Count - 1]).StatusDescription -eq "Reporting")
{
write-host "=============================="
write-host "in progress updates"
write-host "=============================="
#use the progress properties, i.e., RecordType and PercentComplete to update the UI
$child.Progress[$child.Progress.Count - 1]
#store this Id so we can ignore progress until Id changes
$lastActivityId = $child.Progress[$child.Progress.Count - 1].ActivityId
}
#period at which the UI is updated
start-sleep -milliseconds 250
}
$retObj = Receive-Job -Name "UniqueJobName"
write-host "=============================="
write-host "receive job"
write-host "=============================="
# Because the job may finish before progress is captured
# for each item, use the returned values to update the UI one last time
foreach ($key in $retObj.GetEnumerator())
{
"retObj=" + $key.name + " " + $key.Value.status + " " + $key.Value.details
}
#cleanup
Get-Job -Name "UniqueJobName" | Stop-Job
Get-Job -Name "UniqueJobName" | Remove-Job
==============================
in progress updates
==============================
ActivityId : 1
ParentActivityId : -1
Activity : For UI Update: Item A processing complete
StatusDescription : Reporting
CurrentOperation :
PercentComplete : 20
SecondsRemaining : -1
RecordType : Completed
==============================
in progress updates
==============================
ActivityId : 2
ParentActivityId : -1
Activity : For UI Update: Item B processing complete
StatusDescription : Reporting
CurrentOperation :
PercentComplete : 40
SecondsRemaining : -1
RecordType : Completed
==============================
in progress updates
==============================
ActivityId : 3
ParentActivityId : -1
Activity : For UI Update: Item C processing complete
StatusDescription : Reporting
CurrentOperation :
PercentComplete : 60
SecondsRemaining : -1
RecordType : Completed
==============================
in progress updates
==============================
ActivityId : 4
ParentActivityId : -1
Activity : For UI Update: Item D processing complete
StatusDescription : Reporting
CurrentOperation :
PercentComplete : 80
SecondsRemaining : -1
RecordType : Completed
==============================
receive job
==============================
retObj=Item D PASS
retObj=Item E PASS
retObj=Item A FAIL some error description
retObj=Item B FAIL some error description
retObj=Item C PASS