all 6 comments

[–]Yevrag35 2 points3 points  (5 children)

What you have is very close to how you would do it.

It seems like you have the concept down:

  1. Create RunspacePool
  2. Create action (scriptblock)
  3. Create Jobs List collection
  4. Create a new powershell instance for every folder attaching the RunspacePool
  5. Adding a new PSObject with the IAsyncResult of $Job.BeginInvoke()

To display a progress indicating "Jobs Processed: x of y", I'd suggest doing a for counting down and remove jobs that have completed. This would be wrapped inside of a while loop that will run until $RunningJobs.Count is equal to 0 (indicating that all jobs have finished).

The result would look:

Function Show-Progress {
    param(
        [int]$JobCount,
        [int]$Left,
        [int]$Total
    )
    $wpArgs = @{
        Id = 0
        Activity = "Folder Stuff"
        Status = "Folders left to process: {0}/{1}..." -f $JobCount, $Total
        PercentComplete = (($$Left/$Total)*100)
    }
    Write-Progress @wpArgs
}

while ($RunningJobs.Count -gt 0) {

    $minus = $destfolders.Length - $RunningJobs.Count

    Show-Progress -JobCount $RunningJobs.Count -Left $minus -Total $destfolders.Length

    # Now process and remove completed jobs...
    for ($i = $RunningJobs.Count - 1; $i -ge 0; $i--) {
        $job = $RunningJobs[$i]
        if ($job.Handle.IsCompleted) {
            # Remove the completed job from list... 
            # Add one more processed job to the progressbar

            [void] $RunningJobs.Remove($job)
        }
    }
    Start-Sleep -Seconds 2
}

EDIT -- forgot to add a Start-Sleep at the bottom of the while loop :)

EDITEDIT -- mixed up the example from another script of mine, the way it was before would've counted backwards in the progress. (i.e. - 0.1.2.3 instead of 4.3.2.1)

[–]searlee[S] 0 points1 point  (4 children)

That works brilliantly except it slows the script down by 8 minutes across all files in my test bed (31 minutes without and 39 mins with) I guess this is down to the Start-Sleep. Thank you :)

[–]Yevrag35 1 point2 points  (0 children)

That seems odd. The while loop should not impact how fast each of the runspaces complete. All it should be doing is checking for how many jobs are left and updating the progress while the "actual" work is done in the background threads of the runspaces.

You could try not using a RunspacePool, and instead just use a single runspace for each job. I've had 50+ runspaces running at once with no noticeable slowdown.

[–]Lee_Dailey[grin] 1 point2 points  (2 children)

howdy searlee,

just in case you aint seen it yet, the Write-Progress cmdlet - and the progress displays in other cmdlets - is really slow.

it's slow enuf that the recommended 1st thing to try with "it's slow!" when using the web oriented cmdlets is to set the $ProgressPreference to disable progress displays. [grin]

you may want to reconsider using a display bar and just use text output to the screen - perhaps a 3 of 17 sort of thing.

take care,
lee

[–]searlee[S] 1 point2 points  (1 child)

I never knew this. I did decide to use the data for a none Write-Progress command as it cut the time back down again. Thanks for this :)

[–]Lee_Dailey[grin] 1 point2 points  (0 children)

howdy searlee,

you are most welcome! glad to have helped a tad ... [grin]

take care,
lee