private/Controls/Invoke-OnUIThread.ps1
|
function Invoke-OnUIThread { <# .SYNOPSIS Marshals code execution to the UI dispatcher thread. Used to safely update WPF controls from background threads #> [CmdletBinding()] param( [Parameter(Mandatory)] [scriptblock]$ScriptBlock, [switch]$Async ) $session = Get-UiSession $dispatcher = $null # Try session window first, then fall back to Application.Current if ($session -and $session.Window) { $dispatcher = $session.Window.Dispatcher } if ($null -eq $dispatcher) { $dispatcher = [System.Windows.Application]::Current.Dispatcher } # No dispatcher - run directly if ($null -eq $dispatcher) { return & $ScriptBlock } # Already on UI thread - execute directly if ($dispatcher.CheckAccess()) { return & $ScriptBlock } # Not on UI thread - marshal to UI thread dispatcher if ($Async) { # Fire and forget [void]$dispatcher.BeginInvoke([Action]$ScriptBlock, $null) } else { # Use BeginInvoke + Wait to avoid deadlock # Direct Invoke would block the calling thread and prevent the dispatcher from processing the request $operation = $dispatcher.BeginInvoke([Func[object]]$ScriptBlock, $null) # Wait for completion without blocking dispatcher $operation.Wait() if ($operation.Status -eq 'Completed') { return $operation.Result } } } |