Powershell: Waiting on C# Events Causes Deadlocks

Created on 14 Nov 2019  路  5Comments  路  Source: PowerShell/PowerShell

When waiting for a C# event to occur (via Register-ObjectEvent), if the main PowerShell thread is blocked, the event action will not fire. This can create a deadlock when waiting on C# events.

Steps to reproduce

$ErrorActionPreference = "Stop"

# launch process with the appropriate args. 
$p = [System.Diagnostics.Process]::new() 
$p.StartInfo.FileName = "notepad.exe" 
$p.StartInfo.Arguments = $null 
$p.EnableRaisingEvents = $true 
$p.Start()

# create a task completion source
$tcs = [System.Threading.Tasks.TaskCompletionSource[Boolean]]::new()

Register-ObjectEvent -InputObject $p -EventName Exited `
    -MessageData $tcs `
    -Action {
        $Event.MessageData.SetResult($true)
    } 

# wait for the program to exit 
$processTask = $tcs.Task

# this deadlocks 
$processTask.Wait()

Expected behavior

The event action fires on a background thread, triggering the task completion source, and the main thread is unblocked.

Actual behavior

The event action does not fire as long as the main thread is blocked.

Environment data

Name                           Value
----                           -----
PSVersion                      6.2.3
PSEdition                      Core
GitCommitId                    6.2.3
OS                             Microsoft Windows 10.0.18363
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

If this is desired behavior, the documentation needs to be updated to indicate that all C# object events, even those that fire on background threads, will not work as long as the main thread is blocked.

Area-Cmdlets-Utility Issue-Question Resolution-Answered

Most helpful comment

@daxian-dbw For reference, here's the bug I opened that covers the documentation issue: https://github.com/MicrosoftDocs/PowerShell-Docs/issues/5097

All 5 comments

If this is desired behavior, the documentation needs to be updated to indicate that all C# object events, even those that fire on background threads, will not work as long as the main thread is blocked.

@iUnknwn Please open new issue in https://github.com/MicrosoftDocs/PowerShell-Docs repo

GitHub
The official PowerShell documentation sources. Contribute to MicrosoftDocs/PowerShell-Docs development by creating an account on GitHub.

@daxian-dbw Can we close this as external (have you issue in Core repo?) or dup?

This is the by design behavior of the powershell eventing.
The c# event is triggered on a background thread, but that event handler is not the Action script block you specified here, but a handler generated by PowerShell to queue an event in the session.
That queued event will trigger the script block action to run on the pipeline thread, so when the pipeline thread is blocked, the action won't be executed.

@iUnknwn Please open an issue in the PowerShell-Docs repo as @iSazonov suggested above.

@daxian-dbw For reference, here's the bug I opened that covers the documentation issue: https://github.com/MicrosoftDocs/PowerShell-Docs/issues/5097

See Wait-Event

Was this page helpful?
0 / 5 - 0 ratings