Thread safe class method defined in Powershell hangs inside a Lazy inside a ConcurrentDictionary
See original GitHub issuePrerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues.
- Refer to the FAQ.
- Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
I have a thread safe class method (it’s static and empty) that is hanging when called inside of a System.Lazy
initializer inside of a System.Collections.Concurrent.ConcurrentDictionary
when used with ForEach-Object -Parallel
. Calling a normal dotnet method works fine (e.g. [System.Convert]::ToString(132456, 2)
), but my [Dead]::Lock()
method call hangs.
This is as far as I was able to strip my repro code down while still causing the hang:
#Requires -Version 7
Write-Host "Starting job`n"
$dict = [System.Collections.Concurrent.ConcurrentDictionary[string, System.Lazy[string]]]::new()
$job = 1..16 | ForEach-Object -AsJob -ThrottleLimit 16 -Parallel {
$threadNum = $_
$dict = $using:dict
class Dead {
# This method should be thread safe(?)
static [void] Lock() {
}
}
[System.Console]::WriteLine("Starting thread #$threadNum")
$lazy = $dict.GetOrAdd("same key", [System.Lazy[string]]::new(
{
# Calling this method causes the script to hang, even though it should(?) be thread safe
[Dead]::Lock()
$okToCall = [System.Convert]::ToString(132456, 2)
return ""
},
[System.Threading.LazyThreadSafetyMode]::ExecutionAndPublication))
[void]$lazy.Value
[System.Console]::WriteLine("Completed thread #$threadNum")
}
try {
while (!$job.Finished.WaitOne(1000)) {
Write-Host "$(Get-Date): Waiting"
}
$job | Receive-Job
Write-Host "`nFinished job`n"
} finally {
$job | Stop-Job
}
Note: you may need to run this a bunch of times to actually see the hang. I’m also running this without my profile to ensure that’s not interfering: pwsh.exe -NoProfile -File $Home\OneDrive\Scripts\bug.ps1
I’ve had independent verification of the hang from at least one other user.
Expected behavior
PS C:\> pwsh.exe -NoProfile -File $Home\OneDrive\Scripts\bug.ps1
Starting job
Starting thread #1
Starting thread #2
Starting thread #3
Starting thread #4
Starting thread #5
Starting thread #6
Starting thread #7
Starting thread #8
Starting thread #9
Starting thread #10
Starting thread #11
Starting thread #12
Starting thread #13
Starting thread #14
Starting thread #15
Starting thread #16
Completed thread #2
Completed thread #6
Completed thread #9
Completed thread #13
Completed thread #3
Completed thread #1
Completed thread #4
Completed thread #5
Completed thread #7
Completed thread #8
Completed thread #10
Completed thread #11
Completed thread #12
Completed thread #14
Completed thread #15
Completed thread #16
Finished job
PS C:\>
Actual behavior
PS C:\> pwsh.exe -NoProfile -File $Home\OneDrive\Scripts\bug.ps1
Starting job
Starting thread #2
Starting thread #1
Starting thread #3
Starting thread #4
Starting thread #5
Starting thread #6
Starting thread #7
Starting thread #8
Starting thread #9
Starting thread #10
Starting thread #11
Starting thread #12
Starting thread #13
Starting thread #14
Starting thread #15
Starting thread #16
10/10/2022 11:52:52: Waiting
10/10/2022 11:52:53: Waiting
10/10/2022 11:52:54: Waiting
10/10/2022 11:52:55: Waiting
10/10/2022 11:52:56: Waiting
10/10/2022 11:52:57: Waiting
10/10/2022 11:52:58: Waiting
10/10/2022 11:52:59: Waiting
10/10/2022 11:53:00: Waiting
10/10/2022 11:53:01: Waiting
10/10/2022 11:53:02: Waiting
Error details
No response
Environment data
Name Value
---- -----
PSVersion 7.2.6
PSEdition Core
GitCommitId 7.2.6
OS Microsoft Windows 10.0.22621
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Visuals
No response
Issue Analytics
- State:
- Created a year ago
- Comments:9 (2 by maintainers)
Top Results From Across the Web
Making ConcurrentDictionary GetOrAdd thread safe using ...
This post explores the GetOrAdd function of ConcurrentDictionary, the level of thread safety it provides, and ways to add additional ...
Read more >Are non-concurrent collections safe inside ...
My thought is that as long as the highest level collection is configured to be concurrent/thread safe, it doesn't matter if the nested ......
Read more >Using Lazy and ConcurrentDictionary to ensure a thread- ...
In this post, Mike Larah discusses how to ensure your C# collections are thread-safe, only run-once, and are lazy-loaded.
Read more >Add and Remove Items from a ConcurrentDictionary
Read an example of how to add, retrieve, update, and remove items from the ConcurrentDictionary collection class in .NET.
Read more >Untitled
Alama bakmie keliinici di blok m, How to measure inside leg of jeans, ... Apa yang dimaksud dengan business process improvement, Circuit queen...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Oh yeah, you’re good, we just mark it for tracking purposes 😃 We would always much prefer duplicates over issues going unreported ❤️
Especially with issues as impossible to search for as this 😁
This is a known issue (and somewhat by design) for static methods. Very recently a PR was merged adding a way to strip runspace affinity for a class. Once that makes it to a preview, that will be the recommended way of handling it.
In earlier versions you can move to instance methods and use the work around described in https://github.com/PowerShell/PowerShell/issues/3651#issuecomment-306968528