If instead, I uncomment and use the while ($signal -eq $false) loop
that has a WaitOne(5000) then the timers actions each time the WaitOne
times out but this is NOT the behaviour I was hoping for and is STA
behaviour not MTA.
I need to wait on this signal event which basically tells my script to
end while letting timer events run in the background. How can I do this
so that my timer actions run real time in the background and ideally can
call write-host into my application. Right now with the infinite
WaitOne(), they do not run at all!
Here is a sample script that hangs till I signal the ManualResetEvent
from my app at which point all the queued actions run with a timestamp
that shows it was not just the write-host that was hanging but the
actions themselves did not run at all.
## This example shows undesired action behaviour when the main thread
is waiting on a ManualResetEvent
## Since Powershell is MTA I should have thought this would work but
only works if
## I do something on the main script thread that runs ever once in a
while like the snippet I have commented out
$timer = New-Object System.Timers.Timer
$SendAlert =
{
$time1 = [DateTime]::Now
write-host "SendAlert fired from script block at $time1."
}
try
{
write-host "PowershellTriggerDemo was entered."
## start a timer
$timer.Interval = 5000 # every 5 seconds in ms
Register-ObjectEvent -inputObject $timer -EventName Elapsed
-SourceIdentifier Timer.Elapsed -action $SendAlert
$timer.Enabled=$true
# wait until we are told to quit while the timer goes off on a
background thread sending events
write-host "Value of CmdManQuitEvent is '$CmdManQuitEvent'"
#### The script blocks hang till this event is signaled
$CmdManQuitEvent.WaitOne()
#the below allows the timer action to run but is not my ideal
design
##$signal = $false
##while ($signal -eq $false)
##{
##$time2 = [DateTime]::Now
##$signaled = $CmdManQuitEvent.WaitOne(5000, $false) ## wait 5
seconds and wake so actions can run
##write-host "signal value is $signaled at $time2"
##}
$time3 = [DateTime]::Now
write-host "PowershellTriggerDemo ending normally at $time3."
}
catch
{
# say why we failed
$msg = $error[0].Exception.Message
write-host "PowershellTriggerDemo failed for reason '$msg'."
exit
}
finally
{
$timer.Enabled=$false
# this should run but no output is written or saved
unRegister-Event -SourceIdentifier Timer.Elapsed
write-host "Finally ran."
}
--
CodeSlinger
MTA does not equal multithreaded. At any one time, powershell has one
active thread in the MTA pool servicing input from the console;
blocking this thread will most likely not allow it to service events.
If you wish to wait on events and/or jobs (which service events),
investigate Wait-Job and Wait-Event. PowerShell has its own finely
tuned infrastructure to work with asynchronous eventing; just because
waithandles are available to use (purely incidentally through access
to the .net framework), it doesn't mean you can impose your own
intepretation on their framework.
-Oisin