-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Optimize OnDrawItem to prevent GDI resource exhaustion by caching scaled icon size #14123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #14123 +/- ##
===================================================
+ Coverage 76.01271% 77.15542% +1.14271%
===================================================
Files 3279 3279
Lines 645325 645339 +14
Branches 47720 47721 +1
===================================================
+ Hits 490529 497914 +7385
+ Misses 145491 143737 -1754
+ Partials 9305 3688 -5617
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR addresses a critical GDI resource exhaustion issue that causes crashes in owner-drawn controls during high-frequency drawing operations. The fix introduces intelligent caching of scaled icon widths to prevent repeated GDI object creation in hot code paths.
Key Changes:
- Implemented a dictionary-based cache using (Cursor, DPI) tuples to store computed icon widths
- Refactored
OnDrawItemto use the cached values instead of repeatedly creating Icon objects - Added proper cache cleanup in the
End()method to prevent memory leaks
src/System.Windows.Forms.Design/src/System/Drawing/Design/CursorEditor.CursorUI.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Design/src/System/Drawing/Design/CursorEditor.CursorUI.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Design/src/System/Drawing/Design/CursorEditor.CursorUI.cs
Show resolved
Hide resolved
src/System.Windows.Forms.Design/src/System/Drawing/Design/CursorEditor.CursorUI.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Design/src/System/Drawing/Design/CursorEditor.CursorUI.cs
Show resolved
Hide resolved
ricardobossan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All LGTM!
Fixes #14122
Root Cause
The exception:
An object could not be created, possibly due to a lack of memory, but most likely due to invalid inputwas triggered because of how
OnDrawItemhandled icon creation in a high-frequency drawing path:Repeated GDI object creation in hot path
Each call to OnDrawItem executed:
This pattern allocates multiple unmanaged GDI resources per draw cycle. Under heavy redraw (scrolling, hover, DPI changes), these allocations accumulate quickly, exhausting GDI handles.
Proposed changes
Customer Impact
Regression?
Risk
Screenshots
Before
When using a PropertyGrid to edit properties of type Cursor, resizing the Cursor UITypeEditor drop-down window causes the application to stop responding or crash.
ResizeCursorEdiorIssue.mp4
After
AfterChanges.mp4
Test methodology
Test environment(s)
Microsoft Reviewers: Open in CodeFlow