none
PowerShell: System.Timers.Timer не срабатывает событие Disposed. RRS feed

  • Вопрос

  • Здравствуйте!

    Пытаюсь освоить в PowerShell таймер (System.Timers.Timer), на текущий момент почему-то не происходит событие Disposed. Проще объяснить по коду:

    $timer = New-Object System.Timers.Timer
    $timer.Interval = 1000
    $timer.AutoReset = $true
    $timer.Enabled = $true
    
    $Counter = 0
    Register-ObjectEvent -SourceIdentifier EventTest -InputObject $timer -EventName Elapsed -Action {
    	$Counter++
    	Write-Host "<TIMER>: $Counter"
    	if ($Counter -ge 5) {
    		Write-Host("Trying to stop")
    		$timer.Enable = $false
    		$timer.Dispose
    		Unregister-Event -SourceIdentifier EventTest
    	}
    }
    
    Register-ObjectEvent -SourceIdentifier TimerStop -InputObject $timer -EventName Disposed -Action { Write-Host("Timer stopped.") }

    Событие Elapsed происходит и в консоли отображается:

    <TIMER>: 1
    <TIMER>: 2
    <TIMER>: 3
    <TIMER>: 4
    <TIMER>: 5
    Trying to stop

    Далее я надеюсь увидеть "Timer stopped.", но этого не происходит. Получается, что не наступает событие Disposed? Или я как-то не так пытаюсь это реализовать?

    В целом хочу написать скрипт, который будет выводить MessageBox, где будет идти обратный отсчёт с помощью таймера. По завершению отсчёта таймер должен уничтожаться, а скрипт выполнять некоторое действие.

    Подскажите, пожалуйста, что делаю не так (или почему оно не работает?!).


    8 декабря 2017 г. 7:40

Ответы

  • Можно, но передавать, требуется по другому:

    $timer = New-Object System.Timers.Timer
    $timer.Interval = 1000
    $timer.AutoReset = $true
    $timer.Enabled = $true
    
    Register-ObjectEvent -SourceIdentifier TimerStop -InputObject $timer -EventName Disposed -Action { Write-Host("Timer stopped.") }
    $pso = new-object psobject -prop @{foo=$timer}
    Register-ObjectEvent -SourceIdentifier EventTest -InputObject $timer -EventName Elapsed -Message $pso -Action  {
    	$Counter++
    	Write-Host "<TIMER>: $Counter"
    	if ($Counter -ge 5) {
    		Write-Host("Trying to stop")
    		$event.messagedata.foo.Enabled = $false
    		$event.messagedata.foo.Dispose()
    		Unregister-Event -SourceIdentifier EventTest
    	}
    }

    Или объявить область global:

    $global:timer = New-Object System.Timers.Timer
    $timer.Interval = 1000
    $timer.AutoReset = $true
    $timer.Enabled = $true
    
    $Counter = 0
    
    Register-ObjectEvent -SourceIdentifier EventTest -InputObject $timer -EventName Elapsed -Action {
    	$Counter++
    	Write-Host "<TIMER>: $Counter"
    	if ($Counter -ge 5) {
    		Write-Host("Trying to stop")
    		$timer.Enabled = $false
    		$timer.Dispose()
    		Unregister-Event -SourceIdentifier EventTest
    	}
    }
    
    Register-ObjectEvent -SourceIdentifier TimerStop -InputObject $timer -EventName Disposed -Action { Write-Host("Timer stopped.") }


    • Изменено KazunEditor 9 декабря 2017 г. 9:42
    • Помечено в качестве ответа KazunEditor 12 декабря 2017 г. 5:46
    8 декабря 2017 г. 9:24
    Отвечающий

Все ответы

  • $timer.Dispose() - это метод и вынести метод из блока Action,т.к. нет там такой перменной.
    • Изменено KazunEditor 8 декабря 2017 г. 7:58
    8 декабря 2017 г. 7:49
    Отвечающий
  • $timer.Dispose() - это метод и вынести метод из блока Action,т.к. нет там такой перменной.

    Куда его вынести? Если я вставлю его сразу за:
    Register-ObjectEvent -SourceIdentifier EventTest... 
    то он тут же уничтожится и не будет происходить отсчёт таймера. Не очень понял, куда Вы меня направляете...
    8 декабря 2017 г. 8:02
  • Register-ObjectEvent -SourceIdentifier EventTest -InputObject $timer -EventName Elapsed -Action  {
    	$Counter++
    	Write-Host "<TIMER>: $Counter"
    	if ($Counter -ge 5) {
    		Write-Host("Trying to stop")
    		Register-ObjectEvent -SourceIdentifier TimerStop -InputObject $timer -EventName Disposed -Action { Write-Host("Timer stopped.") }
    		$timer.Enabled = $false
    		$timer.Dispose()
    		Unregister-Event -SourceIdentifier EventTest
    	}
    }

    Вывод:

    PS > <timer>: 1

    PS > <timer>: 2

    PS > <timer>: 3

    PS > <timer>: 4

    PS > <timer>: 5

    Trying to stop

    Timer stopped.

    • Изменено KazunEditor 8 декабря 2017 г. 8:48
    8 декабря 2017 г. 8:44
    Отвечающий
  • Скрипт работает, спасибо!

    А можете ещё подсказать?

    Получается, что я не могу в начале скрипта указать кучу Register-ObjectEvent и верить в то, что они отработают при наступлении события, указанного в них?

    В указанном Вами примере получается, что подписываться на событие Disposed нужно непосредственно перед вызовом самого метода Dispose?

    Или подписка на событие Elapsed как-то мешает дальнейшей подписке на событие Disposed?

    8 декабря 2017 г. 9:17
  • Можно, но передавать, требуется по другому:

    $timer = New-Object System.Timers.Timer
    $timer.Interval = 1000
    $timer.AutoReset = $true
    $timer.Enabled = $true
    
    Register-ObjectEvent -SourceIdentifier TimerStop -InputObject $timer -EventName Disposed -Action { Write-Host("Timer stopped.") }
    $pso = new-object psobject -prop @{foo=$timer}
    Register-ObjectEvent -SourceIdentifier EventTest -InputObject $timer -EventName Elapsed -Message $pso -Action  {
    	$Counter++
    	Write-Host "<TIMER>: $Counter"
    	if ($Counter -ge 5) {
    		Write-Host("Trying to stop")
    		$event.messagedata.foo.Enabled = $false
    		$event.messagedata.foo.Dispose()
    		Unregister-Event -SourceIdentifier EventTest
    	}
    }

    Или объявить область global:

    $global:timer = New-Object System.Timers.Timer
    $timer.Interval = 1000
    $timer.AutoReset = $true
    $timer.Enabled = $true
    
    $Counter = 0
    
    Register-ObjectEvent -SourceIdentifier EventTest -InputObject $timer -EventName Elapsed -Action {
    	$Counter++
    	Write-Host "<TIMER>: $Counter"
    	if ($Counter -ge 5) {
    		Write-Host("Trying to stop")
    		$timer.Enabled = $false
    		$timer.Dispose()
    		Unregister-Event -SourceIdentifier EventTest
    	}
    }
    
    Register-ObjectEvent -SourceIdentifier TimerStop -InputObject $timer -EventName Disposed -Action { Write-Host("Timer stopped.") }


    • Изменено KazunEditor 9 декабря 2017 г. 9:42
    • Помечено в качестве ответа KazunEditor 12 декабря 2017 г. 5:46
    8 декабря 2017 г. 9:24
    Отвечающий