Break the reference chain so old containers can be garbage collected.#11717
Break the reference chain so old containers can be garbage collected.#11717gpaskaleva-msft wants to merge 2 commits into
Conversation
…ualized ItemsControls When UIA clients enumerate a virtualized ItemsControl (e.g. DataGrid), ElementProxy CCWs are created for each automation peer. Previously, when children were replaced (e.g. due to collection rebinding), the old peers were never disconnected from UIA Core. The COM references held by UIA kept the CCW ref count > 0, pinning the managed peers and their entire visual sub-trees in memory indefinitely. This fix calls UiaDisconnectProvider on removed children's ElementProxy CCWs during UpdateChildrenInternal, causing UIA Core to release its COM references. This allows the CCW ref count to drop to zero so the managed peers can be garbage collected. Key changes: - Add DisconnectPeerFromUia() that disconnects a peer by calling UiaDisconnectProvider on its ElementProxy (non-recursive to avoid disconnecting shared container peers in virtualized controls) - Move the StructureChanged event check after disconnect logic in UpdateChildrenInternal so disconnection happens regardless of event registration - P/Invoke UiaDisconnectProvider from UIAutomationCore.dll Note: UIA clients may observe ElementNotAvailableException when accessing properties of stale elements after disconnection. This is standard UIA behavior that well-behaved clients already handle. Fixes #11337 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@gpaskaleva-msft please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement ( “Agreement” ) is agreed to by the party signing below ( “You” ), 1. Definitions. “Code” means the computer software code, whether in human-readable or machine-executable form, “Project” means any of the projects owned or managed by .NET Foundation and offered under a license “Submit” is the act of uploading, submitting, transmitting, or distributing code or other content to any “Submission” means the Code and any other copyrightable material Submitted by You, including any 2. Your Submission. You must agree to the terms of this Agreement before making a Submission to any 3. Originality of Work. You represent that each of Your Submissions is entirely Your 4. Your Employer. References to “employer” in this Agreement include Your employer or anyone else 5. Licenses. a. Copyright License. You grant .NET Foundation, and those who receive the Submission directly b. Patent License. You grant .NET Foundation, and those who receive the Submission directly or c. Other Rights Reserved. Each party reserves all rights not expressly granted in this Agreement. 6. Representations and Warranties. You represent that You are legally entitled to grant the above 7. Notice to .NET Foundation. You agree to notify .NET Foundation in writing of any facts or 8. Information about Submissions. You agree that contributions to Projects and information about 9. Governing Law/Jurisdiction. This Agreement is governed by the laws of the State of Washington, and 10. Entire Agreement/Assignment. This Agreement is the entire agreement between the parties, and .NET Foundation dedicates this Contribution License Agreement to the public domain according to the Creative Commons CC0 1. |
Fixes #11337
Description
ElementProxy.cs:
_peermade non-readonly +ClearPeer()method — allowsDisconnectPeerFromUiato sever the strong proxy → peer reference immediately (for non-UIElement peers likeDataGridItemAutomationPeer)AutomationPeer.cs:
EnsureChildren()disconnect logic — detects removed peers when_childrenis refreshed during UIA traversal and callsDisconnectPeerFromUiaon them.DisconnectPeerFromUiachanges:proxy.ClearPeer()— severs proxy→peer strong referenceDispatcher.BeginInvokeforUiaDisconnectProvider— defers COM disconnect to outside UIA callback contextpeer._children = null; peer._childrenValid = false;— the critical fix that breaks the chain from disconnected peer → cached cell peers → old DataGridCell/Row containersRegression
No
Testing
Test Environment
Tests Performed
peer._children = null; peer._childrenValid = false;in DisconnectPeerFromUiaRisk
Microsoft Reviewers: Open in CodeFlow