Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Conversation

@hartez
Copy link
Contributor

@hartez hartez commented Feb 28, 2020

Description of Change

This issue occurs under a very specific set of circumstances:

  • A Forms element has a bound property
  • The element's renderer has been created
  • The element and the renderer are not attached to the view hierarchy
  • The only reference to the element is a weak reference via the binding
  • The garbage collector has just run and determined that the renderer is collectible
  • The source of the binding for the element's bound property updates

For garbage collection to occur, the link between the managed and native objects referenced by the renderer needs to be severed. So the object's Handle is set to IntPtr.Zero. However, before the actual collection can occur, the source property changes.

When the source property changes, the weak reference to the element with the bound property is checked, and that creates a strong reference. The property changed handler fires, which ultimately causes the renderer's OnElementPropertyChanged method to run. However, at this point the renderer's native object is no longer eligible for anything; any attempt to reference it throws the ObjectDisposedException.

This change adds a check for a zeroed Handle before running the rest of the OnElementPropertyChanged method, which avoids the exception. The element and renderer can later be succesfully collected by the GC.

The element and the renderer are not attached to the view hierarchy

This circumstance is rare. It's trivial to recreate it artificially (see the unit tests included with this PR), but in practice it mostly happens when properties are bound to a (relatively) long-lived source; see issue #9431 for an example where CollectionView items have properies bound to the Page itself.

Issues Resolved

API Changes

None

Platforms Affected

  • Android

Behavioral/Visual Changes

None

Before/After Screenshots

Not applicable

Testing Procedure

Automated tests.

PR Checklist

  • Targets the correct branch
  • Tests are passing (or failures are unrelated)

samhouts and others added 2 commits February 27, 2020 15:26
from garbage collection by a weak referenced property changed handler

Fixes #9431; Fixes #5560; Fixes #8607; Fixes #6587; Fixes #9412;
@samhouts samhouts changed the base branch from master to 4.6.0 February 28, 2020 01:23
@hartez hartez removed the request for review from StephaneDelcroix February 28, 2020 05:14
@hartez
Copy link
Contributor Author

hartez commented Feb 28, 2020

Curses! Forgot to deal with the legacy renderers....

@hartez hartez added the DO-NOT-MERGE-!!! 🛑 This is in progress and needs to be updated before it can be merged. label Feb 28, 2020
@hartez hartez removed the DO-NOT-MERGE-!!! 🛑 This is in progress and needs to be updated before it can be merged. label Feb 28, 2020
@hartez
Copy link
Contributor Author

hartez commented Feb 28, 2020

Okay, added checks for the old renderers.


protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
{
if (View.IsDisposed())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I know when chatting you had mentioned you wanted to make this method call as light as possible because how often PropertyChanged is called.

That being said then should we try only calling this for relevant properties?

I realize the code for that is a bit heavy but it would let us check for a few more things without the performance cost. Maybe the method calls at each line could use an action of sorts to get called

CallPropertyChangedMethod(UpdateMainText, this);

And then CallPropertyChangedMethod would check this to see if it should still call UpdateMainText and then at that point the check and any additional behavior could be generalized.

Copy link
Contributor

@PureWeen PureWeen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the IsDisposed checks should also be added to the tracker as well.

@hartez
Copy link
Contributor Author

hartez commented Mar 10, 2020

All the IsDisposed checks should also be added to the tracker as well.

Done.

@samhouts samhouts added approved Has two approvals, no pending reviews, and no changes requested ControlGallery p/iOS 🍎 p/Android a/boxview labels Mar 10, 2020
@samhouts samhouts added a/collectionview i/high Completely doesn't work, crashes, or is unusably slow, has no obvious workaround; occurs less often t/bug 🐛 a/listview Problems with the ListView/TableView hacktoberfest 🍻 a/fastrenderers a/label labels Mar 10, 2020
@hartez hartez merged commit e87323b into 4.6.0 Mar 11, 2020
@samhouts samhouts added this to the 4.6.0 milestone Mar 25, 2020
@samhouts samhouts deleted the fix-9431 branch June 26, 2020 00:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a/boxview a/collectionview a/fastrenderers a/label a/listview Problems with the ListView/TableView approved Has two approvals, no pending reviews, and no changes requested ControlGallery hacktoberfest 🍻 i/high Completely doesn't work, crashes, or is unusably slow, has no obvious workaround; occurs less often p/Android p/iOS 🍎 t/bug 🐛

Projects

None yet

4 participants