WPF ShowDialog()中の非同期イベント
ShowDialog()中に非同期イベントを処理できない。
Powershell でWPFのShowDialog()を処理中に非同期イベントが発生しても処理されない件、原因不明ながら回避策にて対応。
なお、イベントの発生と処理は別物。発生時刻をイベントのプロパティTimeGeneratedで確認。処理時刻をハンドラでの(Get-Date)で確認する。
まずは問題
$win = xxx でWindow生成 $win.ShowDialog()
UI内のイベントで Start-Process のExited EventをRegister-ObjectEventで登録。これはUIスレッドで発生しないため、非同期イベント。
プロセスが終了してもUIスレッドで処理されない。
但し、UIスレッド内でGet-Eventした時に前記イベント発生。
イベントの生成時刻プロパティを見ると、UIスレッドで処理された時刻よりかなり前に発生していた。
- 対策1 UIのボタンなどの処理で、Get-Eventする。
- 対策2 DispatcherTimerで定期的にイベント処理を発生させる。
対策1
単純にボタンでGet-Event。ボタン名が"kita", Windowが$winとすると、
$kita = $win.FindName("kita") $kita.add_click( {Get-Event})
kitaボタンを押すと、非同期イベントがあれば処理してくれる。
対策2
タイマーイベントの副作用で、非同期イベントを処理。ある意味、前記のkitaボタンをタイマーが自動で押してくれる様なもの。
$proc = Start-Process cmd -Passthru $timer = New-Object System.Windows.Threading.DispatcherTimer $timer.interval = New-Object TimeSpan(0,0,1) $timer.add_tick({ Write-Host "tick" if ( $this.tag ){ # イベント発生済み # イベントジョブ削除 $this.Stop() Remove-Job -id ($this.tag).id $this.tag = $null }) $timer.IsEnabled = $true $timer.Start() $timer.tag = $null $ev = Register-ObjectEvent $proc -EventName Exited -Messagedata @{timer=$timer;ev=$ev;dispatcher=[System.Windows.Threading.Dispatcher]::CurrentDispatcher } $timer -Action { $data = $event.MessageData $timer = $data.timer $timer.tag = $data.ev Unregister-Event -SourceIdentifier $EventSubscriber.Name # 何らかの後処理。 # 本処理PSEventJobがJobとして残っているので、どこかで削除する必要あり。 # UIスレッド処理: $eventは引数 $data.dispatcher.BeginInvoke({ # uiスレッド処理 }, @($event)) }
参考
http://d.hatena.ne.jp/omoisan/touch/20090711/1249783732
http://main.tinyjoker.net/Tech/CSharp/WPF/�̥����åɤ������Ǥ������.html
http://www.atmarkit.co.jp/ait/spv/1411/04/news133.html
http://ari-it.doorblog.jp/archives/30059088.html
Dispatcher class
https://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcher(v=vs.110).aspx#メソッド
Peocess Exited event
https://msdn.microsoft.com/ja-jp/library/system.diagnostics.process.exited(v=vs.90).aspx
WPF timer使用例
https://code.msdn.microsoft.com/windowsdesktop/XAMLCVB-WPF-Windows-WPF-2aab6085
DispatcherTimer
https://msdn.microsoft.com/ja-jp/library/ms615945.aspx#継承階層
IsEnabled
https://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatchertimer.isenabled.aspx
tag property
https://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatchertimer.tag.aspx
TimeSpan
https://msdn.microsoft.com/ja-jp/library/system.timespan(v=vs.110).aspx
https://msdn.microsoft.com/ja-jp/library/bk8a3558(v=vs.110).aspx