`Owner` property should be cleaned to avoid memory leaks
Is your feature request related to a problem? Please describe
Not all objects are cleaned after disposing of Control accessible objects because of keeping some value in Owner.
Needs to suggest the opportunity to null Owner in accessible objects to avoid memory leaks.
Describe the solution you'd like and alternatives you've considered
The suggestion is based on #6886 comment (see description)
Will this feature affect UI controls?
No
Another possible option to avoid changes to the nullability contract is to do something like the following. It will require a risk assessment as well though.
private Control? _owner;
public Control Owner => _owner ?? throw new ObjectDisposedException(...);
internal void ClearOwnerControl()
{
_owner = null;
}
I see 3 ways:
-
Use Igor's suggestion. We will avoid changing and adding a lot of null-checks for all control AOs. But it will lead for many unexpected unstable exceptions, because UIA likes to call our methods after disposing a control and disconnecting the object (eg. FragmentNavigate). So anyway we must to add checks for all methods of all inherited objects to avoid the exceptions or we can make a workaround - create a new private property (eg. "IsOwnerDisposed") inside
AccessibleObject.csand check it for every UIA API (eg.UiaCore.IRawElementProviderFragment.Navigate). Thereby we will implement a part of the approach "Don't create an accessible object if its control is not created". Something like that:
-
Make
Ownernullable. Add a lot of null-checks for all inherited accessible objects for all methods and properties. It will change nullable statement for public API (eg. Owner can be null now). This is huge work. But it allows to make it safe. -
Use one supporting static property/method that returns one Control instance. Put this one global object as
Ownerfor any disposed accessible object. Thereby we will avoid nullable changes and exceptions. This global object will return some incorrect abstract values, but we shouldn't care about it for disposed objects. Main aim - avoid exceptions.
@RussKie, @Tanya-Solyanik, what do you like?
I like the idea of tracking when the owner is disposed, and for Control-derived owners this shouldn't be too difficult to implement (see Disposed event).
Building on top of that, we could also have a shared static dummy control that we'd return when the real owner is disposed, but wouldn't we be hiding error scenarios that we'd discover (by the virtue of a failure) otherwise?
As for the adding checks - we'd have to add them one way or another.
Sorry I missed this when I was doing #9164. While changing the nullability is a breaking change it:
- Isn't a binary breaking change
- Has a low probability of impact to external users
- Allows writing more resilient code for CCWs that are being held by native code (without try..catching everywhere)
@Tanya-Solyanik should this be closed now?
Yeah, we can close it now that #9224 was resolved.