Action-based object events sometimes lost

后端 未结 1 1820
离开以前
离开以前 2021-01-20 11:55

Suppose an object referenced in some PS code is known to have fired 100 events between Register-ObjectEvent and Unregister-Event. Expectation would

1条回答
  •  无人共我
    2021-01-20 12:57

    You are "losing" events because you end your script too early. Your event action defined by Register-ObjectEvent ([Utils.StaticEventTest]) Fired -SourceIdentifier $srcId -Action { $global:recvd++ } will be executed asynchronously to your script. If I repeat what you did, I get even worse results (maybe due to a virtual environment):

    C:\Users\user\Desktop>for /l %n in (1, 1, 10) do @powershell.exe  -executionPolicy remoteSigned -file test.ps1
    total 1000 events fired - 17 received
    total 1000 events fired - 100 received
    total 1000 events fired - 202 received
    total 1000 events fired - 16 received
    total 1000 events fired - 3 received
    total 1000 events fired - 120 received
    total 1000 events fired - 1 received
    total 1000 events fired - 162 received
    total 1000 events fired - 1 received
    total 1000 events fired - 27 received
    

    But when I add a Start-Sleep -Seconds 5 after your for-loop, I get this result (at least in my environment):

    C:\Users\user\Desktop>for /l %n in (1, 1, 10) do @powershell.exe  -executionPolicy remoteSigned -file test.ps1
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    total 1000 events
    

    So all events you fired are there, no event is lost. But if you want to see the action taken on them right after you fired them, you have to wait until all (asynchronous) actions have been performed.

    Of course, Start-Sleep with a fixed time span is not an option here, because you cannot know how long it takes for a system to execute all actions. But it shows the reason, why you think you are losing events.

    A possible way to wait for your events would be this line after your for-loop:

    while ($global:recvd -lt $fired) {Start-Sleep -Milliseconds 10}
    

    This even works for 100.000 events per iteration (really tried):

    C:\Users\user\Desktop>for /l %n in (1, 1, 10) do @powershell.exe  -executionPolicy remoteSigned -file test.ps1
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    total 100000 events
    

    Not a single event lost. This makes me believe that the firing and listening for events works as expected. I am not able to reproduce any counterproof.

    0 讨论(0)
提交回复
热议问题