Sleeping within a loop

This topic contains 4 replies, has 2 voices, and was last updated by Profile photo of Michael Maher Michael Maher 7 months, 2 weeks ago.

  • Author
    Posts
  • #37895
    Profile photo of Michael Maher
    Michael Maher
    Participant

    Hi Folks,

    I've stuck on a section of a script I am creating.

    Here is a simplified version of the problem I am hitting. I wish to run the command for a duration of a minute with a 10 second interval between each iteration.

    $timeout = New-TimeSpan -Minutes 1
    $stopwatch = [diagnostics.stopwatch]::StartNew()
    
    While  ($stopwatch.elapsed -lt $timeout) {Get-ChildItem | ForEach-Object {
            [PSCustomObject] @{
                'Name'= $_.Name
                'Timestamp'= (get-date).ToLongTimeString()
                'Type'= $_.Attributes
                } 
             }         
        Start-Sleep -Seconds 10          
    } 
    

    The issue I have is there is a 10 second sleep anything is returned. Then I get the output from two iterations at once.

    Name                Timestamp      Type
    ----                ---------      ----
    DNS Lookup          11:18:16  Directory
    iplookup.ps1        11:18:16    Archive
    networkcommands.txt 11:18:16    Archive
    pingAllDCs.ps1      11:18:16    Archive
    wifiChannel.ps1     11:18:16    Archive
    DNS Lookup          11:18:26  Directory
    iplookup.ps1        11:18:26    Archive
    networkcommands.txt 11:18:26    Archive
    pingAllDCs.ps1      11:18:26    Archive
    

    I'd like the first iteration to output straightaway. I tried a Do . . While loop but that behaved the same.

    I next tried changing the flow by putting the execution code in a function. This did not work.

    Function TestCode{
        Get-ChildItem | ForEach-Object {
                [PSCustomObject] @{
                    'Name'= $_.Name
                    'Timestamp'= (get-date).ToLongTimeString()
                    'Type'= $_.Attributes
                    } 
        }
    }
    
    $timeout = New-TimeSpan -Minutes 1
    $stopwatch = [diagnostics.stopwatch]::StartNew()
    testcode
    
    While  ($stopwatch.elapsed -lt $timeout) {      
        Start-Sleep -Seconds 10
        testcode          
    } 
    

    Moving Start-Sleep -Seconds 10 outside the While loops above is no use either as it's ignored and the loop continiously cycles

    Thanks,

    Michael

  • #37897
    Profile photo of Matt Bloomfield
    Matt Bloomfield
    Participant

    Are you having the same problem with your simplified example?

    I copied and pasted it into the ISE and it worked as expected; it output the directory contents immediately, followed by a 10 second delay, then output the contents again.

  • #37900
    Profile photo of Michael Maher
    Michael Maher
    Participant

    Hi Matt,

    Yes I have the problem with my simplified script (both samples) in the ISE/WMF 5.0 on Windows 10.

    After your post I went on to my AWS server and the code ran fine. I thought it was a problem with my logic and it didn't dawn on me to check enviromentals.

    I've a little bit of profile customisation on my Windows 10 box nothing major but I'll need to eliminate that.

    Thanks for testing.

    Regards,

    Michael

  • #37901
    Profile photo of Matt Bloomfield
    Matt Bloomfield
    Participant

    Just fired up the Windows 10 laptop and I can replicate the behaviour (I previously tested on Win8.1 with PS v4.0).

    The problem appears to be something to do with the object creation (or the output of the object) rather than the sleep. If you don't create an object and just do Write-Output $_.Name it works as expected. I have tried other methods of creating the object and they don't get output until after the second iteration.

  • #37903
    Profile photo of Michael Maher
    Michael Maher
    Participant

    Yes I think you're right.

    My guess is that the Custom Object object isn't fully initialized and the script moves on.

    If I slow it down (even by 1 millisecond) it works fine.

    $timeout = New-TimeSpan -Minutes 1
    $stopwatch = [diagnostics.stopwatch]::StartNew()
    
    While  ($stopwatch.elapsed -lt $timeout) {Get-ChildItem | ForEach-Object {
            [PSCustomObject] @{
                'Name'= $_.Name
                'Timestamp'= (get-date).ToLongTimeString()
                'Type'= $_.Attributes
                } 
                Start-Sleep -milliseconds 1 # Take a breather!
             }         
        Start-Sleep -Seconds 10       
    } 
    

You must be logged in to reply to this topic.