Skip to content
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

Unregister hooks in ScrollViewerAssist when the ScrollViewer is unloaded #3133

Merged
merged 2 commits into from Mar 16, 2023

Conversation

chris-crowther
Copy link
Contributor

Fixes #3130.

This covers the necessary clean-up of registered Win32 hooks and event handlers for the SupportHorizontalScroll and BubbleVerticalScroll attached properties.

To unregister the HwndSourceHook we have to capture the HwndSource in the Loaded event. I'm happy to consider an alternative approach.

I was tempted to promote the duplicated OnLoaded and OnUnloaded local methods to instance level methods as they are not property-specific.

@@ -119,10 +124,24 @@ static void OnLoaded(ScrollViewer scrollViewer, Action<ScrollViewer> doOnLoaded)
}
}

static void OnUnloaded(ScrollViewer scrollViewer, Action<ScrollViewer> doOnUnloaded)
{
if (!scrollViewer.IsLoaded)
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry for barging in on this code review; I was curious. 😃

This guard is a bit suspicious to me. Why do we only want to listen for the Unloaded event if the ScrollViewer is not already loaded? I think the situation where it IS loaded is equally relevant. This would be a scenario where the AP is not statically set in XAML, but applied at runtime after the ScrollViewer has loaded. I acknowledge this may not be the most common use case, but it is still possible. In short, I think we should handle both the ScrollViewer.IsLoaded=true/false cases.

Another thing to consider is using weak event handlers. Both the Loaded and Unloaded event handlers are currently registered as strong event handlers which unregister themselves when the corresponding event fires. However, I think there are scenarios where this will not work - not particularly related to your changes though:

If the ScrollViewer resides in a TabÌtem, it will be loaded and unloaded multiple times when switching between the tabs. The current implementation only seems to wire up the hooks when the AP changes which means it will register for the Loaded event at startup. However, after navigating away from the TabItem and back to it again, the Unloaded event will fire, removing the hook, and then there is nothing listening for the "second" Loaded event to re-register the hook. Perhaps this could be mitigated by simply using weak event handlers and never unregistering them?

This comment also applies for the changes to the other AP.

Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That guard is certainly suspicious! I'm going to step through the code again in the demo app...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nicolaihenriksen, you're right; this needs to support a variety of scenarios, including:

  • Tab items with permanent content in which the ScrollViewer will be loaded and unloaded multiple times
  • Tab items with transient content in which the ScrollViewer will be loaded once, unloaded once, and then (hopefully) garbage-collected
  • Runtime changes to the attached properties after the ScrollViewer has been loaded

I've pushed some changes which should cover all of the above.

@Keboo Keboo added this to the 4.9.0 milestone Mar 10, 2023
@Keboo Keboo self-requested a review March 10, 2023 16:35
@Keboo
Copy link
Member

Keboo commented Mar 16, 2023

Awesome. Thank you for putting this together

@Keboo Keboo merged commit 4569526 into MaterialDesignInXAML:master Mar 16, 2023
2 checks passed
@chris-crowther chris-crowther deleted the fix3130 branch March 17, 2023 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Potential memory leak in ScrollViewerAssist
3 participants